akanjs 3.1.0-rc.2 → 3.1.0-rc.21
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/base/baseEnv.ts +5 -2
- package/client/device.ts +1 -1
- package/client/frameConfig.ts +2 -2
- package/client/href.ts +35 -0
- package/client/index.ts +1 -0
- package/client/makePageProto.tsx +3 -2
- package/client/router.ts +6 -4
- package/client/rscNavigation.ts +1 -1
- package/client/transitionTypes.ts +0 -4
- package/client/translator.ts +16 -0
- package/client/types.ts +3 -2
- package/client/viewportMeta.ts +23 -8
- package/client/webManifest.ts +5 -3
- package/common/TrustedProxy.ts +14 -0
- package/common/codeAgentWire.ts +8 -1
- package/common/index.ts +1 -0
- package/common/interpolateTranslation.ts +17 -3
- package/common/isEmail.ts +1 -1
- package/common/localeConfig.ts +10 -4
- package/common/markdownSpans.ts +1 -1
- package/common/restClient.ts +3 -1
- package/common/routeConvention.ts +4 -4
- package/common/trimSlashes.ts +11 -0
- package/common/types.ts +1 -1
- package/constant/fieldInfo.ts +2 -2
- package/constant/fieldPlan.ts +80 -0
- package/constant/index.ts +3 -0
- package/constant/inputParser.ts +148 -0
- package/constant/invalidInputError.ts +13 -0
- package/constant/serialize.ts +36 -20
- package/constant/types.ts +1 -1
- package/constant/via.ts +2 -0
- package/dictionary/base.dictionary.ts +4 -0
- package/dictionary/trans.ts +8 -0
- package/document/database.ts +3 -6
- package/document/documentSchema.ts +1 -1
- package/document/noDocumentError.ts +6 -1
- package/fetch/client/fetchClient.ts +2 -1
- package/fetch/client/sliceInitHandle.ts +2 -3
- package/fetch/fetchType/appliedReturn.type.ts +3 -1
- package/fetch/types.ts +4 -2
- package/index.ts +2 -0
- package/package.json +31 -21
- package/server/akanApp.ts +15 -3
- package/server/akanServer.ts +34 -14
- package/server/artifact/routeClientCache.ts +4 -5
- package/server/artifact/routeSeedIndexStore.ts +3 -20
- package/server/artifact/routeSeedMatcher.ts +70 -0
- package/server/console.ts +1 -1
- package/server/di/diLifecycle.ts +16 -7
- package/server/imageOptimizer.ts +1 -1
- package/server/index.ts +1 -0
- package/server/machine/machineAccount.ts +28 -3
- package/server/machine/machineToken.ts +27 -3
- package/server/mcp/McpDispatcher.ts +2 -3
- package/server/mcp/McpExecutionContext.ts +9 -3
- package/server/migration/docPath.ts +121 -0
- package/server/migration/index.ts +15 -0
- package/server/migration/migrationChangeLog.ts +86 -0
- package/server/migration/migrationChanges.ts +70 -0
- package/server/migration/migrationCommand.ts +179 -0
- package/server/migration/migrationContext.ts +53 -0
- package/server/migration/migrationDefinition.ts +87 -0
- package/server/migration/migrationError.ts +45 -0
- package/server/migration/migrationLedger.ts +172 -0
- package/server/migration/migrationLock.ts +103 -0
- package/server/migration/migrationParams.ts +122 -0
- package/server/migration/migrationPulse.ts +39 -0
- package/server/migration/migrationRunner.ts +525 -0
- package/server/migration/migrationScope.ts +93 -0
- package/server/migration/migrationTable.ts +258 -0
- package/server/migration/migrations.ts +57 -0
- package/server/ops/opsCommand.ts +30 -1
- package/server/resolver/CascadeRunner.ts +15 -2
- package/server/resolver/signal.resolver.ts +35 -55
- package/server/routeState.ts +0 -6
- package/server/rscClient.tsx +22 -37
- package/server/rscNavigationState.ts +3 -5
- package/server/rscScrollRestoration.ts +116 -0
- package/server/rscWorker.tsx +12 -19
- package/server/sitemap.ts +4 -4
- package/server/tunnel/TunnelAgent.ts +9 -1
- package/server/webRouter.ts +17 -2
- package/service/agent.service.ts +21 -1
- package/service/endpointCacheKeys.ts +35 -0
- package/service/index.ts +1 -0
- package/service/injectInfo.ts +2 -2
- package/service/predefinedAdaptor/anthropicLlm.ts +37 -17
- package/service/predefinedAdaptor/database.adaptor.ts +15 -0
- package/service/predefinedAdaptor/documentTransfer.ts +50 -0
- package/service/predefinedAdaptor/endpointCacheControl.adaptor.ts +19 -0
- package/service/predefinedAdaptor/index.ts +1 -0
- package/service/predefinedAdaptor/llm.adaptor.ts +7 -0
- package/service/predefinedAdaptor/openaiDialect.ts +53 -17
- package/service/predefinedAdaptor/openaiLlm.ts +1 -1
- package/service/predefinedAdaptor/sql/MigrationTables.ts +90 -0
- package/service/predefinedAdaptor/sql/RawDocumentTable.ts +200 -0
- package/service/predefinedAdaptor/sql/SqlDocumentStore.ts +6 -2
- package/service/predefinedAdaptor/sql/SqliteInsightSession.ts +4 -1
- package/service/predefinedAdaptor/sql/dialect/postgres.ts +0 -1
- package/service/predefinedAdaptor/sql/dialect/sqlite.ts +0 -1
- package/service/predefinedAdaptor/sql/types.ts +3 -1
- package/service/predefinedAdaptor/storage.adaptor.ts +19 -0
- package/signal/endpointCache.ts +23 -7
- package/signal/endpointErrorContract.ts +37 -0
- package/signal/endpointIdempotency.ts +5 -3
- package/signal/endpointInfo.ts +4 -1
- package/signal/endpointRateLimit.ts +6 -2
- package/signal/exception.ts +4 -1
- package/signal/index.ts +1 -0
- package/signal/mcp/McpDocument.ts +16 -1
- package/signal/mcp/McpUriTemplate.ts +1 -1
- package/signal/middlewareChain.ts +105 -0
- package/signal/openapi/openapi.ts +46 -2
- package/signal/serializer/fetch.serializer.ts +1 -0
- package/signal/signalContext.ts +110 -82
- package/signal/slice.ts +2 -2
- package/signal/trace.ts +8 -2
- package/signal/types.ts +13 -0
- package/store/action.ts +102 -42
- package/store/agent/ScreenImage.ts +166 -0
- package/store/agent/ScreenReader.ts +2 -1
- package/store/agent/StoreSurfaceSource.ts +41 -2
- package/store/agent/index.ts +2 -1
- package/store/databaseStateNames.ts +1 -0
- package/store/formUploadOf.ts +41 -0
- package/store/index.ts +1 -0
- package/store/liveInsert.ts +2 -2
- package/store/state.ts +9 -1
- package/store/stateBuilder.ts +8 -2
- package/store/storeInstance.ts +12 -3
- package/store/withSelector.ts +2 -2
- package/types/client/href.d.ts +11 -0
- package/types/client/index.d.ts +1 -0
- package/types/client/rscNavigation.d.ts +1 -1
- package/types/client/transitionTypes.d.ts +0 -2
- package/types/client/translator.d.ts +2 -0
- package/types/common/codeAgentWire.d.ts +7 -0
- package/types/common/index.d.ts +1 -0
- package/types/common/trimSlashes.d.ts +2 -0
- package/types/common/types.d.ts +1 -1
- package/types/constant/fieldInfo.d.ts +2 -2
- package/types/constant/fieldPlan.d.ts +33 -0
- package/types/constant/index.d.ts +3 -0
- package/types/constant/inputParser.d.ts +11 -0
- package/types/constant/invalidInputError.d.ts +8 -0
- package/types/constant/types.d.ts +1 -1
- package/types/dictionary/base.dictionary.d.ts +1 -1
- package/types/dictionary/dictionary.d.ts +3 -3
- package/types/dictionary/trans.d.ts +3 -0
- package/types/document/database.d.ts +2 -3
- package/types/document/documentSchema.d.ts +1 -1
- package/types/document/noDocumentError.d.ts +6 -1
- package/types/fetch/fetchType/appliedReturn.type.d.ts +3 -1
- package/types/fetch/types.d.ts +2 -2
- package/types/index.d.ts +5 -0
- package/types/server/akanServer.d.ts +1 -1
- package/types/server/artifact/routeSeedMatcher.d.ts +8 -0
- package/types/server/di/diLifecycle.d.ts +1 -0
- package/types/server/index.d.ts +1 -0
- package/types/server/machine/machineAccount.d.ts +1 -0
- package/types/server/machine/machineToken.d.ts +9 -0
- package/types/server/migration/docPath.d.ts +20 -0
- package/types/server/migration/index.d.ts +15 -0
- package/types/server/migration/migrationChangeLog.d.ts +27 -0
- package/types/server/migration/migrationChanges.d.ts +27 -0
- package/types/server/migration/migrationCommand.d.ts +33 -0
- package/types/server/migration/migrationContext.d.ts +28 -0
- package/types/server/migration/migrationDefinition.d.ts +42 -0
- package/types/server/migration/migrationError.d.ts +15 -0
- package/types/server/migration/migrationLedger.d.ts +51 -0
- package/types/server/migration/migrationLock.d.ts +34 -0
- package/types/server/migration/migrationParams.d.ts +41 -0
- package/types/server/migration/migrationPulse.d.ts +15 -0
- package/types/server/migration/migrationRunner.d.ts +93 -0
- package/types/server/migration/migrationScope.d.ts +42 -0
- package/types/server/migration/migrationTable.d.ts +52 -0
- package/types/server/migration/migrations.d.ts +12 -0
- package/types/server/migration.d.ts +1 -0
- package/types/server/ops/opsCommand.d.ts +10 -1
- package/types/server/routeState.d.ts +1 -4
- package/types/server/rscNavigationState.d.ts +2 -3
- package/types/server/rscScrollRestoration.d.ts +14 -0
- package/types/server/sitemap.d.ts +1 -1
- package/types/service/agent.service.d.ts +2 -0
- package/types/service/endpointCacheKeys.d.ts +8 -0
- package/types/service/index.d.ts +1 -0
- package/types/service/injectInfo.d.ts +2 -2
- package/types/service/predefinedAdaptor/anthropicLlm.d.ts +9 -4
- package/types/service/predefinedAdaptor/database.adaptor.d.ts +8 -1
- package/types/service/predefinedAdaptor/documentTransfer.d.ts +1 -0
- package/types/service/predefinedAdaptor/endpointCacheControl.adaptor.d.ts +9 -0
- package/types/service/predefinedAdaptor/index.d.ts +1 -0
- package/types/service/predefinedAdaptor/llm.adaptor.d.ts +7 -0
- package/types/service/predefinedAdaptor/openaiDialect.d.ts +20 -5
- package/types/service/predefinedAdaptor/sql/MigrationTables.d.ts +17 -0
- package/types/service/predefinedAdaptor/sql/RawDocumentTable.d.ts +38 -0
- package/types/service/predefinedAdaptor/sql/types.d.ts +1 -0
- package/types/service/predefinedAdaptor/storage.adaptor.d.ts +8 -0
- package/types/signal/endpointCache.d.ts +2 -0
- package/types/signal/endpointErrorContract.d.ts +10 -0
- package/types/signal/endpointIdempotency.d.ts +1 -0
- package/types/signal/endpointRateLimit.d.ts +1 -1
- package/types/signal/exception.d.ts +4 -1
- package/types/signal/index.d.ts +1 -0
- package/types/signal/middlewareChain.d.ts +11 -0
- package/types/signal/signalContext.d.ts +2 -6
- package/types/signal/slice.d.ts +1 -1
- package/types/signal/trace.d.ts +1 -1
- package/types/signal/types.d.ts +12 -0
- package/types/store/action.d.ts +2 -0
- package/types/store/agent/ScreenImage.d.ts +27 -0
- package/types/store/agent/StoreSurfaceSource.d.ts +1 -1
- package/types/store/agent/index.d.ts +2 -1
- package/types/store/databaseStateNames.d.ts +1 -0
- package/types/store/formUploadOf.d.ts +9 -0
- package/types/store/index.d.ts +1 -0
- package/types/store/state.d.ts +7 -1
- package/types/store/stateBuilder.d.ts +2 -1
- package/types/store/storeInstance.d.ts +2 -2
- package/types/store/withSelector.d.ts +1 -1
- package/types/ui/Agent/Composer.d.ts +2 -0
- package/types/ui/Agent/Menu.d.ts +2 -0
- package/types/ui/CsrImage.d.ts +2 -0
- package/types/ui/Data/CardList.d.ts +1 -1
- package/types/ui/Data/Dashboard.d.ts +1 -1
- package/types/ui/Data/Insight.d.ts +1 -1
- package/types/ui/Data/Item.d.ts +2 -2
- package/types/ui/Data/ListContainer.d.ts +1 -1
- package/types/ui/Data/Pagination.d.ts +1 -1
- package/types/ui/Data/TableList.d.ts +1 -1
- package/types/ui/Field/Relation.d.ts +13 -10
- package/types/ui/Field/index.d.ts +4 -4
- package/types/ui/Field/useRelationOptions.d.ts +3 -1
- package/types/ui/Field/useRelationWindow.d.ts +14 -0
- package/types/ui/Image.d.ts +3 -1
- package/types/ui/Load/View.d.ts +1 -1
- package/types/ui/Pagination.d.ts +1 -1
- package/types/ui/Signal/Arg.d.ts +1 -1
- package/types/ui/System/CSR.d.ts +1 -1
- package/types/ui/System/Client.d.ts +1 -1
- package/types/ui/System/SSR.d.ts +1 -1
- package/types/vendor/@akanjs/native/packages/core/src/plugin.d.ts +3 -3
- package/types/vendor/@akanjs/native/packages/desktop/src/page-veto.d.ts +1 -1
- package/types/vendor/@akanjs/native/packages/desktop/src/plugin.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/auth-session/src/desktop.d.ts +2 -2
- package/types/vendor/@akanjs/native/plugins/auth-session/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/autostart/src/desktop.d.ts +2 -2
- package/types/vendor/@akanjs/native/plugins/autostart/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/badge/src/desktop.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/badge/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/badge/src/web.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/biometric/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/camera/src/desktop.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/camera/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/camera/src/web.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/clipboard/src/desktop.d.ts +2 -2
- package/types/vendor/@akanjs/native/plugins/clipboard/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/clipboard/src/web.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/contacts/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/device/src/desktop.d.ts +2 -2
- package/types/vendor/@akanjs/native/plugins/device/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/device/src/web.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/dialog/src/desktop.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/dialog/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/dialog/src/web.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/dock/src/desktop.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/dock/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/file-picker/src/desktop.d.ts +2 -2
- package/types/vendor/@akanjs/native/plugins/file-picker/src/web.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/filesystem/src/desktop.d.ts +2 -2
- package/types/vendor/@akanjs/native/plugins/filesystem/src/web.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/haptics/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/haptics/src/web.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/http/src/desktop.d.ts +2 -2
- package/types/vendor/@akanjs/native/plugins/http/src/web.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/keep-awake/src/desktop.d.ts +2 -2
- package/types/vendor/@akanjs/native/plugins/keep-awake/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/keep-awake/src/web.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/opener/src/desktop.d.ts +2 -2
- package/types/vendor/@akanjs/native/plugins/opener/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/opener/src/web.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/preferences/src/desktop.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/preferences/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/preferences/src/web.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/secure-storage/src/desktop.d.ts +2 -2
- package/types/vendor/@akanjs/native/plugins/secure-storage/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/share/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/share/src/web.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/single-instance/src/desktop.d.ts +2 -2
- package/types/vendor/@akanjs/native/plugins/splash-screen/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/splash-screen/src/web.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/sqlite/src/desktop.d.ts +2 -2
- package/types/vendor/@akanjs/native/plugins/toast/src/index.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/toast/src/web.d.ts +1 -1
- package/types/vendor/@akanjs/native/plugins/window/src/index.d.ts +2 -2
- package/types/vendor/@akanjs/native/plugins/window-state/src/desktop.d.ts +2 -2
- package/types/vendor/@akanjs/native/plugins/window-state/src/index.d.ts +1 -1
- package/types/vendor/use-agentic/Compaction.d.ts +3 -1
- package/types/vendor/use-agentic/Reference.d.ts +9 -1
- package/types/vendor/use-agentic/ToolOutput.d.ts +6 -1
- package/types/vendor/use-agentic/ToolReturn.d.ts +18 -0
- package/types/vendor/use-agentic/Transcript.d.ts +7 -0
- package/types/vendor/use-agentic/index.d.ts +1 -0
- package/types/vendor/use-agentic/types.d.ts +6 -0
- package/types/webkit/useDebounce.d.ts +1 -1
- package/ui/Agent/Chat.tsx +1 -0
- package/ui/Agent/Composer.tsx +2 -0
- package/ui/Agent/Menu.tsx +5 -1
- package/ui/Agent/agentSessionOf.ts +15 -8
- package/ui/Agent/mentionDraft.ts +2 -3
- package/ui/Agent/useReferenceMenu.ts +1 -0
- package/ui/Agent/useSlashMenu.ts +1 -0
- package/ui/Clipboard.tsx +1 -0
- package/ui/CsrImage.tsx +3 -1
- package/ui/Data/CardList.tsx +1 -1
- package/ui/Data/Dashboard.tsx +1 -1
- package/ui/Data/Insight.tsx +1 -1
- package/ui/Data/Item.tsx +5 -2
- package/ui/Data/ListContainer.tsx +2 -2
- package/ui/Data/Pagination.tsx +1 -1
- package/ui/Data/TableList.tsx +1 -1
- package/ui/DraggableList.tsx +1 -0
- package/ui/Field/Collection.tsx +4 -0
- package/ui/Field/Relation.tsx +33 -14
- package/ui/Field/useRelationOptions.ts +33 -5
- package/ui/Field/useRelationWindow.ts +50 -0
- package/ui/Image.tsx +4 -4
- package/ui/Input.tsx +1 -0
- package/ui/Layout/Sider.tsx +1 -1
- package/ui/Link/Anchor.tsx +7 -5
- package/ui/Load/Units.tsx +17 -7
- package/ui/Load/View.tsx +2 -2
- package/ui/Model/Edit.tsx +1 -1
- package/ui/Model/EditModal.tsx +11 -5
- package/ui/Model/New.tsx +1 -1
- package/ui/Model/SureToRemove.tsx +1 -0
- package/ui/Model/ViewEditModal.tsx +17 -5
- package/ui/Model/ViewModal.tsx +2 -2
- package/ui/ObjectId.tsx +5 -1
- package/ui/Pagination.tsx +1 -1
- package/ui/Signal/Arg.tsx +1 -3
- package/ui/Signal/Doc.tsx +5 -1
- package/ui/System/CSR.tsx +1 -1
- package/ui/System/Client.tsx +1 -1
- package/ui/System/Reconnect.tsx +1 -1
- package/ui/System/SSR.tsx +3 -36
- package/ui/ToggleSelect.tsx +2 -0
- package/ui/styles.css +10 -103
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeBridge.swift +3 -2
- package/vendor/@akanjs/native/packages/cli/src/lib/addons.ts +4 -1
- package/vendor/@akanjs/native/packages/cli/src/lib/apk.ts +2 -2
- package/vendor/@akanjs/native/packages/cli/src/lib/codegen.ts +1 -1
- package/vendor/@akanjs/native/packages/cli/src/lib/csp.ts +4 -3
- package/vendor/@akanjs/native/packages/cli/src/lib/googleservices.ts +7 -1
- package/vendor/@akanjs/native/packages/cli/src/lib/hmr.ts +8 -5
- package/vendor/@akanjs/native/packages/cli/src/lib/html.ts +18 -3
- package/vendor/@akanjs/native/packages/cli/src/lib/manifestmerge.ts +1 -1
- package/vendor/@akanjs/native/packages/cli/src/lib/plist.ts +2 -4
- package/vendor/@akanjs/native/packages/cli/src/lib/toolchains.ts +1 -1
- package/vendor/@akanjs/native/packages/cli/src/lib/updates.ts +10 -4
- package/vendor/@akanjs/native/packages/cli/src/lib/xml.ts +4 -3
- package/vendor/@akanjs/native/packages/cli/src/platforms/android.ts +3 -3
- package/vendor/@akanjs/native/packages/core/src/kernel.ts +3 -3
- package/vendor/@akanjs/native/packages/core/src/live.ts +1 -0
- package/vendor/@akanjs/native/packages/core/src/plugin.ts +5 -3
- package/vendor/@akanjs/native/packages/desktop/src/host.ts +13 -5
- package/vendor/@akanjs/native/packages/desktop/src/lifecycle.ts +1 -0
- package/vendor/@akanjs/native/packages/desktop/src/page-veto.ts +1 -1
- package/vendor/@akanjs/native/packages/desktop/src/plugin.ts +4 -1
- package/vendor/@akanjs/native/plugins/camera/src/web.ts +3 -3
- package/vendor/@akanjs/native/plugins/file-picker/src/index.ts +4 -1
- package/vendor/@akanjs/native/plugins/local-notifications/src/web.ts +1 -1
- package/vendor/@akanjs/native/plugins/secure-storage/src/desktop.ts +1 -1
- package/vendor/@akanjs/native/plugins/share/src/options.ts +1 -1
- package/vendor/@akanjs/native/plugins/single-instance/src/desktop.ts +3 -2
- package/vendor/@akanjs/native/plugins/updates/src/desktop.ts +4 -1
- package/vendor/@akanjs/native/plugins/window/src/index.ts +2 -2
- package/vendor/use-agentic/Compaction.ts +38 -7
- package/vendor/use-agentic/Reference.ts +16 -9
- package/vendor/use-agentic/ToolOutput.ts +25 -3
- package/vendor/use-agentic/ToolReturn.ts +32 -0
- package/vendor/use-agentic/ToolRunner.ts +15 -13
- package/vendor/use-agentic/Transcript.ts +38 -2
- package/vendor/use-agentic/WIRE.md +20 -0
- package/vendor/use-agentic/index.ts +1 -0
- package/vendor/use-agentic/types.ts +6 -0
- package/webkit/McpAppAgent.ts +12 -2
- package/webkit/RenderLayer.tsx +23 -4
- package/webkit/useDebounce.ts +23 -14
- package/client/viewTransition.ts +0 -10
- package/types/client/viewTransition.d.ts +0 -3
package/server/rscClient.tsx
CHANGED
|
@@ -2,8 +2,6 @@ import { createElement, type ReactNode, startTransition, type Usable, use, useLa
|
|
|
2
2
|
import { hydrateRoot } from "react-dom/client";
|
|
3
3
|
import { createFromReadableStream } from "react-server-dom-webpack/client.browser";
|
|
4
4
|
import type {} from "../client/rscNavigation";
|
|
5
|
-
import { transitionTypes, viewTransitionClassOf } from "../client/transitionTypes";
|
|
6
|
-
import { addTransitionType } from "../client/viewTransition";
|
|
7
5
|
import {
|
|
8
6
|
type AkanHeadSnapshotV1,
|
|
9
7
|
type AkanRouterStateV1,
|
|
@@ -34,6 +32,7 @@ import {
|
|
|
34
32
|
rememberRscCacheNode,
|
|
35
33
|
resolveCachedRscPatchNavigation,
|
|
36
34
|
} from "./rscNavigationState";
|
|
35
|
+
import { RscScrollRestoration } from "./rscScrollRestoration";
|
|
37
36
|
import { commitAkanSegmentOutletPatch, resetAkanSegmentOutletPatches } from "./rscSegmentOutlet";
|
|
38
37
|
|
|
39
38
|
type InlineRscChunk = [1, string] | [3, string];
|
|
@@ -156,14 +155,12 @@ function commitRscPatchNavigation({
|
|
|
156
155
|
target,
|
|
157
156
|
patch,
|
|
158
157
|
replace,
|
|
159
|
-
|
|
160
|
-
bumpScrollToTop,
|
|
158
|
+
requestScroll,
|
|
161
159
|
}: {
|
|
162
160
|
target: string;
|
|
163
161
|
patch: Extract<RscFetchResult, { type: "patched" }>;
|
|
164
162
|
replace?: boolean;
|
|
165
|
-
|
|
166
|
-
bumpScrollToTop?: () => void;
|
|
163
|
+
requestScroll?: () => void;
|
|
167
164
|
}): boolean {
|
|
168
165
|
const patchThenable = patch.patchedNode.thenable;
|
|
169
166
|
if (!patchThenable) throw new Error("[rscClient] validated RSC patch is missing a thenable");
|
|
@@ -182,7 +179,7 @@ function commitRscPatchNavigation({
|
|
|
182
179
|
return;
|
|
183
180
|
}
|
|
184
181
|
commitHistory(target, replace);
|
|
185
|
-
|
|
182
|
+
requestScroll?.();
|
|
186
183
|
} catch {
|
|
187
184
|
if (headApplied) rollbackPreparedAkanHeadSnapshotPatch(preparedHeadPatch);
|
|
188
185
|
if (outletCommitted) resetAkanSegmentOutletPatches();
|
|
@@ -197,10 +194,12 @@ function akanHistoryState(replace: boolean, shallow = false) {
|
|
|
197
194
|
const idx = (window.history.state as { __akanRouter?: { idx?: unknown } } | null)?.__akanRouter?.idx;
|
|
198
195
|
const current = Number.isInteger(idx) ? (idx as number) : 0;
|
|
199
196
|
const shallowState = shallow ? { shallow: true, rendered: renderedHref } : {};
|
|
200
|
-
|
|
197
|
+
const scrollState = replace ? scrollRestoration.replaceEntry() : scrollRestoration.pushEntry();
|
|
198
|
+
return { __akanRouter: { idx: replace ? current : current + 1, ...scrollState, ...shallowState } };
|
|
201
199
|
}
|
|
202
200
|
|
|
203
201
|
let renderedHref = normalizeHref(window.location.href);
|
|
202
|
+
const scrollRestoration = new RscScrollRestoration();
|
|
204
203
|
const pathnameOf = (href: string) => new URL(href).pathname;
|
|
205
204
|
|
|
206
205
|
function commitHistory(target: string, replace: boolean | undefined) {
|
|
@@ -209,13 +208,6 @@ function commitHistory(target: string, replace: boolean | undefined) {
|
|
|
209
208
|
renderedHref = target;
|
|
210
209
|
}
|
|
211
210
|
|
|
212
|
-
function viewTransitionTypeOf(transition: string | undefined, push: boolean): string | null {
|
|
213
|
-
const type = transitionTypes.find((candidate) => candidate === transition);
|
|
214
|
-
if (!type || type === "none") return null;
|
|
215
|
-
if (window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) return null;
|
|
216
|
-
return viewTransitionClassOf(type, push ? "push" : "pop");
|
|
217
|
-
}
|
|
218
|
-
|
|
219
211
|
/** Writes the entry without asking the server for the page; only a change that keeps the rendered path qualifies. */
|
|
220
212
|
function navigateShallow(target: string, replace: boolean | undefined): boolean {
|
|
221
213
|
if (pathnameOf(target) !== pathnameOf(renderedHref)) return false;
|
|
@@ -336,12 +328,11 @@ function rememberPatchedRouteState(tree: RscSegmentCacheNode, patchedNode: RscSe
|
|
|
336
328
|
|
|
337
329
|
function Root(): ReactNode {
|
|
338
330
|
const [thenable, setThenable] = useState<RscThenable>(initialThenable);
|
|
339
|
-
const [
|
|
331
|
+
const [scrollRequest, setScrollRequest] = useState<{ scrollY: number } | null>(null);
|
|
340
332
|
|
|
341
333
|
useLayoutEffect(() => {
|
|
342
|
-
if (
|
|
343
|
-
|
|
344
|
-
}, [scrollToTopTick]);
|
|
334
|
+
if (scrollRequest) scrollRestoration.scrollTo(scrollRequest.scrollY);
|
|
335
|
+
}, [scrollRequest]);
|
|
345
336
|
|
|
346
337
|
globalThis.__AKAN_RSC_CLEAR_CACHE__ = () => {
|
|
347
338
|
rscCache.clear();
|
|
@@ -419,7 +410,8 @@ function Root(): ReactNode {
|
|
|
419
410
|
if (options.shallow && navigateShallow(normalizeHref(href), options.replace)) return;
|
|
420
411
|
const navId = ++navigationSeq;
|
|
421
412
|
const target = normalizeHref(href);
|
|
422
|
-
const
|
|
413
|
+
const scrollY = options.scrollY ?? ((options.scrollToTop ?? true) ? 0 : undefined);
|
|
414
|
+
const requestScroll = scrollY === undefined ? undefined : () => setScrollRequest({ scrollY });
|
|
423
415
|
try {
|
|
424
416
|
let nextNode = rscCache.get(target);
|
|
425
417
|
const servedFromCache = !!nextNode;
|
|
@@ -447,8 +439,7 @@ function Root(): ReactNode {
|
|
|
447
439
|
target,
|
|
448
440
|
patch: replayedPatch,
|
|
449
441
|
replace: options.replace,
|
|
450
|
-
|
|
451
|
-
bumpScrollToTop: () => setScrollToTopTick((tick) => tick + 1),
|
|
442
|
+
requestScroll,
|
|
452
443
|
})
|
|
453
444
|
) {
|
|
454
445
|
currentCommitFromCache = true;
|
|
@@ -473,8 +464,7 @@ function Root(): ReactNode {
|
|
|
473
464
|
target,
|
|
474
465
|
patch: fetched,
|
|
475
466
|
replace: options.replace,
|
|
476
|
-
|
|
477
|
-
bumpScrollToTop: () => setScrollToTopTick((tick) => tick + 1),
|
|
467
|
+
requestScroll,
|
|
478
468
|
})
|
|
479
469
|
) {
|
|
480
470
|
currentCommitFromCache = false;
|
|
@@ -516,11 +506,6 @@ function Root(): ReactNode {
|
|
|
516
506
|
});
|
|
517
507
|
|
|
518
508
|
await nextNode.thenable;
|
|
519
|
-
|
|
520
|
-
const viewTransitionType = viewTransitionTypeOf(
|
|
521
|
-
options.pop ? currentRouterState?.transition : nextNode.routerState?.transition,
|
|
522
|
-
!options.pop,
|
|
523
|
-
);
|
|
524
509
|
const committed = commitLatestRscNavigation({
|
|
525
510
|
cache: rscCache,
|
|
526
511
|
href: target,
|
|
@@ -528,10 +513,6 @@ function Root(): ReactNode {
|
|
|
528
513
|
maxEntries: MAX_RSC_CACHE_ENTRIES,
|
|
529
514
|
startTransition,
|
|
530
515
|
commitThenable: (node) => {
|
|
531
|
-
if (viewTransitionType && addTransitionType) {
|
|
532
|
-
addTransitionType("akan-nav");
|
|
533
|
-
addTransitionType(viewTransitionType);
|
|
534
|
-
}
|
|
535
516
|
currentCommitFromCache = servedFromCache;
|
|
536
517
|
resetAkanSegmentOutletPatches();
|
|
537
518
|
setThenable(node.thenable);
|
|
@@ -539,8 +520,7 @@ function Root(): ReactNode {
|
|
|
539
520
|
updateHistory: () => {
|
|
540
521
|
commitHistory(target, options.replace);
|
|
541
522
|
},
|
|
542
|
-
|
|
543
|
-
bumpScrollToTop: () => setScrollToTopTick((tick) => tick + 1),
|
|
523
|
+
requestScroll,
|
|
544
524
|
navId,
|
|
545
525
|
getCurrentNavId: () => navigationSeq,
|
|
546
526
|
});
|
|
@@ -559,13 +539,15 @@ function Root(): ReactNode {
|
|
|
559
539
|
window.addEventListener("popstate", (event) => {
|
|
560
540
|
const here = normalizeHref(window.location.href);
|
|
561
541
|
const entry = (event.state as { __akanRouter?: { shallow?: boolean; rendered?: string } } | null)?.__akanRouter;
|
|
542
|
+
const scrollY = scrollRestoration.traverseTo(event.state);
|
|
562
543
|
|
|
563
544
|
const keepsPage = (entry?.shallow ? entry.rendered : here) === renderedHref;
|
|
564
545
|
|
|
565
546
|
if (!keepsPage)
|
|
566
547
|
void globalThis
|
|
567
|
-
.__AKAN_RSC_NAVIGATE__?.(window.location.href, { replace: true, scrollToTop: false,
|
|
548
|
+
.__AKAN_RSC_NAVIGATE__?.(window.location.href, { replace: true, scrollToTop: false, scrollY })
|
|
568
549
|
?.catch((error: unknown) => hardNavigateAfterRscFailure(window.location.href, true, error));
|
|
550
|
+
else if (scrollY !== undefined) scrollRestoration.scrollTo(scrollY);
|
|
569
551
|
window.setTimeout(() => {
|
|
570
552
|
if (globalThis.__AKAN_DEV_SYNC_NAVIGATION_APPLYING__) return;
|
|
571
553
|
const href = globalThis.__AKAN_GET_SYNC_ROUTE_HREF__?.(window.location.href) ?? window.location.href;
|
|
@@ -573,5 +555,8 @@ window.addEventListener("popstate", (event) => {
|
|
|
573
555
|
}, 0);
|
|
574
556
|
});
|
|
575
557
|
|
|
576
|
-
const hydrate = () =>
|
|
558
|
+
const hydrate = () => {
|
|
559
|
+
hydrateRoot(document, createElement(Root));
|
|
560
|
+
scrollRestoration.restoreDocumentLoad();
|
|
561
|
+
};
|
|
577
562
|
void Promise.resolve(initialThenable).then(hydrate, hydrate);
|
|
@@ -312,8 +312,7 @@ interface CommitRscNavigationInput<T> {
|
|
|
312
312
|
startTransition: (callback: () => void) => void;
|
|
313
313
|
commitThenable: (thenable: T) => void;
|
|
314
314
|
updateHistory?: () => void;
|
|
315
|
-
|
|
316
|
-
bumpScrollToTop?: () => void;
|
|
315
|
+
requestScroll?: () => void;
|
|
317
316
|
}
|
|
318
317
|
|
|
319
318
|
export function commitRscNavigation<T>({
|
|
@@ -324,14 +323,13 @@ export function commitRscNavigation<T>({
|
|
|
324
323
|
startTransition,
|
|
325
324
|
commitThenable,
|
|
326
325
|
updateHistory,
|
|
327
|
-
|
|
328
|
-
bumpScrollToTop,
|
|
326
|
+
requestScroll,
|
|
329
327
|
}: CommitRscNavigationInput<T>): void {
|
|
330
328
|
rememberRscCacheEntry(cache, href, thenable, maxEntries);
|
|
331
329
|
startTransition(() => {
|
|
332
330
|
commitThenable(thenable);
|
|
333
331
|
updateHistory?.();
|
|
334
|
-
|
|
332
|
+
requestScroll?.();
|
|
335
333
|
});
|
|
336
334
|
}
|
|
337
335
|
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
const RESTORE_WINDOW_MS = 2000;
|
|
2
|
+
const PERSIST_DELAY_MS = 200;
|
|
3
|
+
const userScrollEvents = ["wheel", "touchstart", "keydown", "pointerdown"] as const;
|
|
4
|
+
|
|
5
|
+
interface AkanEntryState {
|
|
6
|
+
key?: unknown;
|
|
7
|
+
scrollY?: unknown;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class RscScrollRestoration {
|
|
11
|
+
#positions = new Map<string, number>();
|
|
12
|
+
#key: string;
|
|
13
|
+
#manual: boolean = false;
|
|
14
|
+
#persistTimer: ReturnType<typeof setTimeout> | null = null;
|
|
15
|
+
#cancelPending: (() => void) | null = null;
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
this.#key = RscScrollRestoration.#entryOf(window.history.state).key ?? RscScrollRestoration.#mintKey();
|
|
19
|
+
|
|
20
|
+
window.addEventListener("scroll", () => this.#schedulePersist(), { passive: true });
|
|
21
|
+
window.addEventListener("pagehide", () => {
|
|
22
|
+
if (this.#persistTimer) this.#persist();
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
pushEntry(): { key: string } {
|
|
27
|
+
this.#settle();
|
|
28
|
+
this.#manual = true;
|
|
29
|
+
window.history.scrollRestoration = "manual";
|
|
30
|
+
this.#positions.set(this.#key, window.scrollY);
|
|
31
|
+
this.#persist();
|
|
32
|
+
this.#key = RscScrollRestoration.#mintKey();
|
|
33
|
+
return { key: this.#key };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
replaceEntry(): { key: string; scrollY?: number } {
|
|
37
|
+
const { scrollY } = RscScrollRestoration.#entryOf(window.history.state);
|
|
38
|
+
return { key: this.#key, ...(scrollY === undefined ? {} : { scrollY }) };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
traverseTo(state: unknown): number | undefined {
|
|
42
|
+
this.#settle();
|
|
43
|
+
this.#positions.set(this.#key, window.scrollY);
|
|
44
|
+
const entry = RscScrollRestoration.#entryOf(state);
|
|
45
|
+
if (entry.key) {
|
|
46
|
+
this.#key = entry.key;
|
|
47
|
+
return this.#positions.get(entry.key) ?? entry.scrollY;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
this.#key = RscScrollRestoration.#mintKey();
|
|
51
|
+
RscScrollRestoration.#writeEntry({ key: this.#key });
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
scrollTo(scrollY: number) {
|
|
56
|
+
this.#cancelPending?.();
|
|
57
|
+
window.scrollTo(0, scrollY);
|
|
58
|
+
if (scrollY === 0 || typeof ResizeObserver === "undefined") return;
|
|
59
|
+
|
|
60
|
+
const observer = new ResizeObserver(() => {
|
|
61
|
+
if (Math.abs(window.scrollY - scrollY) > 1) window.scrollTo(0, scrollY);
|
|
62
|
+
});
|
|
63
|
+
const timer = setTimeout(() => cancel(), RESTORE_WINDOW_MS);
|
|
64
|
+
const cancel = () => {
|
|
65
|
+
observer.disconnect();
|
|
66
|
+
clearTimeout(timer);
|
|
67
|
+
for (const type of userScrollEvents) window.removeEventListener(type, cancel, true);
|
|
68
|
+
if (this.#cancelPending === cancel) this.#cancelPending = null;
|
|
69
|
+
};
|
|
70
|
+
for (const type of userScrollEvents) window.addEventListener(type, cancel, { capture: true, passive: true });
|
|
71
|
+
observer.observe(document.body);
|
|
72
|
+
this.#cancelPending = cancel;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
restoreDocumentLoad() {
|
|
76
|
+
if (window.history.scrollRestoration !== "manual") return;
|
|
77
|
+
this.#manual = true;
|
|
78
|
+
const { scrollY } = RscScrollRestoration.#entryOf(window.history.state);
|
|
79
|
+
if (scrollY !== undefined) this.scrollTo(scrollY);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
#schedulePersist() {
|
|
83
|
+
if (!this.#manual) return;
|
|
84
|
+
if (this.#persistTimer) clearTimeout(this.#persistTimer);
|
|
85
|
+
this.#persistTimer = setTimeout(() => this.#persist(), PERSIST_DELAY_MS);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
#persist() {
|
|
89
|
+
if (this.#persistTimer) clearTimeout(this.#persistTimer);
|
|
90
|
+
this.#persistTimer = null;
|
|
91
|
+
RscScrollRestoration.#writeEntry({ key: this.#key, scrollY: window.scrollY });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
#settle() {
|
|
95
|
+
this.#cancelPending?.();
|
|
96
|
+
if (this.#persistTimer) clearTimeout(this.#persistTimer);
|
|
97
|
+
this.#persistTimer = null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
static #entryOf(state: unknown): { key?: string; scrollY?: number } {
|
|
101
|
+
const entry = (state as { __akanRouter?: AkanEntryState } | null)?.__akanRouter;
|
|
102
|
+
return {
|
|
103
|
+
key: typeof entry?.key === "string" ? entry.key : undefined,
|
|
104
|
+
scrollY: typeof entry?.scrollY === "number" && Number.isFinite(entry.scrollY) ? entry.scrollY : undefined,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
static #writeEntry(fields: AkanEntryState) {
|
|
109
|
+
const state = (window.history.state ?? {}) as { __akanRouter?: object };
|
|
110
|
+
window.history.replaceState({ ...state, __akanRouter: { ...state.__akanRouter, ...fields } }, "");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
static #mintKey() {
|
|
114
|
+
return `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;
|
|
115
|
+
}
|
|
116
|
+
}
|
package/server/rscWorker.tsx
CHANGED
|
@@ -491,18 +491,11 @@ export class RscRenderer {
|
|
|
491
491
|
const beforeLoadedKeys = RouteTreeBuilder.getCacheStats().loadedModuleKeys;
|
|
492
492
|
const cacheDecision = match ? this.#getResultCacheEntry(request, urlObj) : { entry: null };
|
|
493
493
|
const cacheEntry = cacheDecision.entry;
|
|
494
|
-
const targetFrame = match
|
|
495
|
-
? await RouteElementComposer.resolveSsrFramePathRoute({
|
|
496
|
-
pathRoute: match.pathRoute,
|
|
497
|
-
basePath: this.#getBasePath(urlObj),
|
|
498
|
-
})
|
|
499
|
-
: null;
|
|
500
494
|
const targetRouterState = match
|
|
501
495
|
? createAkanRouterState({
|
|
502
496
|
pathRoute: match.pathRoute,
|
|
503
497
|
href: urlObj.href,
|
|
504
498
|
buildId: this.#pagesBundleBuildId,
|
|
505
|
-
transition: targetFrame?.pageState.transition,
|
|
506
499
|
})
|
|
507
500
|
: null;
|
|
508
501
|
const searchParams = parseSearchParams(urlObj.search);
|
|
@@ -886,8 +879,11 @@ export class RscRenderer {
|
|
|
886
879
|
} = {},
|
|
887
880
|
): Promise<FlightRenderResult> {
|
|
888
881
|
const controlRef: { current: RenderControl | null } = { current: null };
|
|
882
|
+
|
|
883
|
+
let isCancelling = false;
|
|
889
884
|
const stream = await renderToReadableStream(element, clientManifest, {
|
|
890
885
|
onError: (error) => {
|
|
886
|
+
if (isCancelling || (options.requestId && this.#cancelledRenderRequests.has(options.requestId))) return;
|
|
891
887
|
if (isAkanRedirectError(error)) {
|
|
892
888
|
const { location, method, status } = error;
|
|
893
889
|
controlRef.current = { type: "redirect", location, method, status };
|
|
@@ -934,6 +930,11 @@ export class RscRenderer {
|
|
|
934
930
|
reportedTheme = theme;
|
|
935
931
|
this.#send({ type: "theme", requestId: options.requestId, theme });
|
|
936
932
|
};
|
|
933
|
+
const cancelWith = async (control: RenderControl | null, cancelled: boolean): Promise<FlightRenderResult> => {
|
|
934
|
+
isCancelling = true;
|
|
935
|
+
await reader.cancel();
|
|
936
|
+
return { chunks, bytes, chunksCount, control, lateControlSent, cancelled };
|
|
937
|
+
};
|
|
937
938
|
const readProbe = () => {
|
|
938
939
|
if (!controlRef.current && options.notFoundProbe?.hit) controlRef.current = { type: "not-found" };
|
|
939
940
|
};
|
|
@@ -960,26 +961,18 @@ export class RscRenderer {
|
|
|
960
961
|
};
|
|
961
962
|
try {
|
|
962
963
|
for (;;) {
|
|
963
|
-
if (options.requestId && this.#cancelledRenderRequests.has(options.requestId))
|
|
964
|
-
await
|
|
965
|
-
return { chunks, bytes, chunksCount, control: null, lateControlSent, cancelled: true };
|
|
966
|
-
}
|
|
964
|
+
if (options.requestId && this.#cancelledRenderRequests.has(options.requestId))
|
|
965
|
+
return await cancelWith(null, true);
|
|
967
966
|
const { value, done } = await reader.read();
|
|
968
967
|
readProbe();
|
|
969
|
-
if (controlRef.current && !sentChunk)
|
|
970
|
-
await reader.cancel();
|
|
971
|
-
return { chunks, bytes, chunksCount, control: controlRef.current, lateControlSent, cancelled: false };
|
|
972
|
-
}
|
|
968
|
+
if (controlRef.current && !sentChunk) return await cancelWith(controlRef.current, false);
|
|
973
969
|
if (controlRef.current && sentChunk) sendLateControl();
|
|
974
970
|
if (done) break;
|
|
975
971
|
|
|
976
972
|
if (!sentChunk && options.requestId) {
|
|
977
973
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
978
974
|
readProbe();
|
|
979
|
-
if (controlRef.current)
|
|
980
|
-
await reader.cancel();
|
|
981
|
-
return { chunks, bytes, chunksCount, control: controlRef.current, lateControlSent, cancelled: false };
|
|
982
|
-
}
|
|
975
|
+
if (controlRef.current) return await cancelWith(controlRef.current, false);
|
|
983
976
|
}
|
|
984
977
|
const chunk = value instanceof Uint8Array ? value : new Uint8Array(value as ArrayBufferLike);
|
|
985
978
|
bytes += chunk.byteLength;
|
package/server/sitemap.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AkanI18nConfig, trimSlashes, trimTrailingSlashes } from "akanjs/common";
|
|
2
2
|
import type { RouteSeedEntry } from "./artifact";
|
|
3
3
|
|
|
4
4
|
export interface DefaultSitemapOptions {
|
|
@@ -24,7 +24,7 @@ export function createDefaultSitemapXml({ origin, basePath, entries, i18n }: Def
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export function createDefaultSitemapUrls({ origin, basePath, entries, i18n }: DefaultSitemapOptions): string[] {
|
|
27
|
-
const normalizedOrigin = origin
|
|
27
|
+
const normalizedOrigin = trimTrailingSlashes(origin);
|
|
28
28
|
const normalizedBasePath = normalizeSegment(basePath ?? "");
|
|
29
29
|
const paths = entries.flatMap((entry) => expandStaticRoute(entry.pattern, normalizedBasePath, i18n.locales));
|
|
30
30
|
return paths.map((pathname) => `${normalizedOrigin}${pathname}`);
|
|
@@ -66,12 +66,12 @@ function expandStaticRoute(pattern: string, basePath: string, locales: readonly
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
function normalizePathname(pathname: string): string {
|
|
69
|
-
const trimmed = pathname.trim()
|
|
69
|
+
const trimmed = trimTrailingSlashes(pathname.trim());
|
|
70
70
|
return trimmed ? `/${trimmed.replace(/^\/+/, "")}` : "/";
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
function normalizeSegment(value: string): string {
|
|
74
|
-
return value.trim()
|
|
74
|
+
return trimSlashes(value.trim());
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
function encodePathSegment(value: string): string {
|
|
@@ -38,6 +38,8 @@ const backoffMs = [1_000, 2_000, 4_000, 8_000, 15_000];
|
|
|
38
38
|
|
|
39
39
|
const coldAttemptLimit = 10;
|
|
40
40
|
|
|
41
|
+
const heartbeatRangeMs = { min: 1_000, max: 300_000 } as const;
|
|
42
|
+
|
|
41
43
|
/** Dials out to the gateway, so its machine needs no public address, no inbound port and no NAT traversal. */
|
|
42
44
|
export class TunnelAgent {
|
|
43
45
|
readonly #options: TunnelAgentOptions;
|
|
@@ -123,7 +125,7 @@ export class TunnelAgent {
|
|
|
123
125
|
this.#everReady = true;
|
|
124
126
|
|
|
125
127
|
this.#attempts = 0;
|
|
126
|
-
this.#startHeartbeat(frame.heartbeatMs
|
|
128
|
+
this.#startHeartbeat(TunnelAgent.#heartbeatOf(frame.heartbeatMs));
|
|
127
129
|
this.#grow();
|
|
128
130
|
this.logger.info(`Tunnel ready: ${frame.urls.join(", ")}`);
|
|
129
131
|
onReady(frame);
|
|
@@ -202,6 +204,12 @@ export class TunnelAgent {
|
|
|
202
204
|
this.#heartbeat = null;
|
|
203
205
|
}
|
|
204
206
|
|
|
207
|
+
static #heartbeatOf(requestedMs: number) {
|
|
208
|
+
return requestedMs >= heartbeatRangeMs.min && requestedMs <= heartbeatRangeMs.max
|
|
209
|
+
? requestedMs
|
|
210
|
+
: tunnelWireContract.defaultHeartbeatMs;
|
|
211
|
+
}
|
|
212
|
+
|
|
205
213
|
#say(frame: TunnelControlFromAgent) {
|
|
206
214
|
if (this.#ws?.readyState !== WebSocket.OPEN) return;
|
|
207
215
|
this.#ws.send(JSON.stringify(frame));
|
package/server/webRouter.ts
CHANGED
|
@@ -242,7 +242,7 @@ export function normalizeRscTargetUrlForHostBasePath(
|
|
|
242
242
|
if (routeMatches(normalized)) return { url: normalized, basePath: candidate };
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
-
return { url: targetUrl, basePath:
|
|
245
|
+
return { url: targetUrl, basePath: targetBasePath };
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
export interface SsrRoutesInputs {
|
|
@@ -367,6 +367,7 @@ export class WebRouter {
|
|
|
367
367
|
const localCsrDir = path.join(process.cwd(), "csr");
|
|
368
368
|
const csrOutputDir = fs.existsSync(localCsrDir) ? localCsrDir : path.join(this.#artifactDir, "csr");
|
|
369
369
|
const publicDir = path.join(process.env.AKAN_APP_DIR ?? path.dirname(Bun.main), "public");
|
|
370
|
+
const shippedPublicFiles = this.#prodMode ? WebRouter.#shippedFiles(publicDir) : null;
|
|
370
371
|
const imageCacheDir = path.join(this.#artifactDir, "image-cache");
|
|
371
372
|
const imageOptimizer = new ImageOptimizer({
|
|
372
373
|
publicDir,
|
|
@@ -566,7 +567,7 @@ export class WebRouter {
|
|
|
566
567
|
}
|
|
567
568
|
|
|
568
569
|
const filePath = resolveStaticPath(publicDir, url.pathname);
|
|
569
|
-
if (filePath && (await
|
|
570
|
+
if (filePath && (await WebRouter.#isPublicFile(filePath, url.pathname, shippedPublicFiles))) {
|
|
570
571
|
this.#requestStats.staticAsset += 1;
|
|
571
572
|
const contentType = Bun.file(filePath).type || "application/octet-stream";
|
|
572
573
|
return WebRouter.#fileResponse(req, filePath, {
|
|
@@ -1116,6 +1117,20 @@ export class WebRouter {
|
|
|
1116
1117
|
this.#logger.warn(`[csr] ${message}`);
|
|
1117
1118
|
return new Response(message, { status: 404, headers: { "Content-Type": "text/plain; charset=utf-8" } });
|
|
1118
1119
|
}
|
|
1120
|
+
|
|
1121
|
+
static async #isPublicFile(filePath: string, pathname: string, shipped: Set<string> | null) {
|
|
1122
|
+
if (shipped && !path.extname(pathname)) return shipped.has(filePath);
|
|
1123
|
+
return await Bun.file(filePath).exists();
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
static #shippedFiles(dir: string): Set<string> {
|
|
1127
|
+
const files = new Set<string>();
|
|
1128
|
+
if (!fs.existsSync(dir)) return files;
|
|
1129
|
+
const scan = new Bun.Glob("**/*").scanSync({ cwd: dir, onlyFiles: true, dot: true, followSymlinks: true });
|
|
1130
|
+
for (const relative of scan) files.add(path.resolve(dir, relative));
|
|
1131
|
+
return files;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1119
1134
|
static #injectBeforeBodyEnd(html: string, snippet: string): string {
|
|
1120
1135
|
const matches = [...html.matchAll(/<\/body\s*>/gi)];
|
|
1121
1136
|
const last = matches.at(-1);
|
package/service/agent.service.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
AgentWireAttachment,
|
|
4
4
|
AgentWireMessage,
|
|
5
5
|
AgentWireReference,
|
|
6
|
+
AgentWireToolResult,
|
|
6
7
|
LlmAccepts,
|
|
7
8
|
LlmTurnRequest,
|
|
8
9
|
} from "./predefinedAdaptor/llm.adaptor";
|
|
@@ -104,12 +105,21 @@ export class AgentService extends serve("agent" as const, ({ plug }) => ({
|
|
|
104
105
|
|
|
105
106
|
/** Swaps an attachment the provider cannot read for a note; dropped silently, it is guessed at from its name. */
|
|
106
107
|
static readable(request: LlmTurnRequest, accepts: LlmAccepts | undefined): LlmTurnRequest {
|
|
107
|
-
if (!request.messages.some(
|
|
108
|
+
if (!request.messages.some(AgentService.carriesFiles)) return request;
|
|
108
109
|
const messages = request.messages.map((message) => AgentService.readableMessage(message, accepts ?? {}));
|
|
109
110
|
return { ...request, messages };
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
private static carriesFiles(message: AgentWireMessage): boolean {
|
|
114
|
+
return !!message.attachments?.length || !!message.toolResults?.some((result) => result.attachments?.length);
|
|
115
|
+
}
|
|
116
|
+
|
|
112
117
|
private static readableMessage(message: AgentWireMessage, accepts: LlmAccepts): AgentWireMessage {
|
|
118
|
+
if (message.role === "tool")
|
|
119
|
+
return {
|
|
120
|
+
...message,
|
|
121
|
+
toolResults: (message.toolResults ?? []).map((result) => AgentService.readableResult(result, accepts)),
|
|
122
|
+
};
|
|
113
123
|
const { attachments = [], ...rest } = message;
|
|
114
124
|
if (!attachments.length) return message;
|
|
115
125
|
const kept = attachments.filter((attachment) => AgentService.isReadable(attachment, accepts));
|
|
@@ -122,6 +132,16 @@ export class AgentService extends serve("agent" as const, ({ plug }) => ({
|
|
|
122
132
|
};
|
|
123
133
|
}
|
|
124
134
|
|
|
135
|
+
private static readableResult(result: AgentWireToolResult, accepts: LlmAccepts): AgentWireToolResult {
|
|
136
|
+
if (!result.attachments?.length) return result;
|
|
137
|
+
const attachments = result.attachments.map((attachment) =>
|
|
138
|
+
AgentService.isReadable(attachment, accepts)
|
|
139
|
+
? attachment
|
|
140
|
+
: { name: attachment.name, mimeType: attachment.mimeType, text: AgentService.note(attachment) },
|
|
141
|
+
);
|
|
142
|
+
return { ...result, attachments };
|
|
143
|
+
}
|
|
144
|
+
|
|
125
145
|
private static isReadable(attachment: AgentWireAttachment, accepts: LlmAccepts): boolean {
|
|
126
146
|
if (attachment.text) return true;
|
|
127
147
|
if (!attachment.data && !attachment.url) return false;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { dayjs } from "akanjs/base";
|
|
2
|
+
import type { CacheAdaptor } from "./predefinedAdaptor/cache.adaptor";
|
|
3
|
+
|
|
4
|
+
export class EndpointCacheKeys {
|
|
5
|
+
static readonly topic = "cache";
|
|
6
|
+
static readonly generationTtlMs = 86_400_000;
|
|
7
|
+
static readonly #generationTopic = "cacheGeneration";
|
|
8
|
+
|
|
9
|
+
static async entryKey(cache: Pick<CacheAdaptor, "get" | "setIfAbsent">, endpoint: string, args: unknown[]) {
|
|
10
|
+
return `${endpoint}:${await EndpointCacheKeys.#generation(cache, endpoint)}:${JSON.stringify(args)}`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static async invalidate(
|
|
14
|
+
cache: Pick<CacheAdaptor, "get" | "set" | "setIfAbsent" | "delete">,
|
|
15
|
+
endpoint: string,
|
|
16
|
+
args?: unknown[],
|
|
17
|
+
) {
|
|
18
|
+
if (args) await cache.delete(EndpointCacheKeys.topic, await EndpointCacheKeys.entryKey(cache, endpoint, args));
|
|
19
|
+
else
|
|
20
|
+
await cache.set(EndpointCacheKeys.#generationTopic, endpoint, crypto.randomUUID(), EndpointCacheKeys.#expiry());
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static async #generation(cache: Pick<CacheAdaptor, "get" | "setIfAbsent">, endpoint: string) {
|
|
24
|
+
const current = await cache.get<string>(EndpointCacheKeys.#generationTopic, endpoint);
|
|
25
|
+
if (current !== undefined) return current;
|
|
26
|
+
const fresh = crypto.randomUUID();
|
|
27
|
+
if (await cache.setIfAbsent(EndpointCacheKeys.#generationTopic, endpoint, fresh, EndpointCacheKeys.#expiry()))
|
|
28
|
+
return fresh;
|
|
29
|
+
return (await cache.get<string>(EndpointCacheKeys.#generationTopic, endpoint)) ?? fresh;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static #expiry() {
|
|
33
|
+
return { expireAt: dayjs().add(EndpointCacheKeys.generationTtlMs, "millisecond") };
|
|
34
|
+
}
|
|
35
|
+
}
|
package/service/index.ts
CHANGED
package/service/injectInfo.ts
CHANGED
|
@@ -91,8 +91,8 @@ export const getDefaultLiveRegistry = (): LiveRegistry => ({
|
|
|
91
91
|
export class InjectInfo<
|
|
92
92
|
Type extends InjectType = any,
|
|
93
93
|
ReturnType = any,
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
_Env extends { [key: string]: any } = never,
|
|
95
|
+
_FieldValue = never,
|
|
96
96
|
> {
|
|
97
97
|
readonly type: Type;
|
|
98
98
|
readonly generateFactory: (options: any) => ReturnType;
|