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
|
@@ -2,6 +2,7 @@ import { adapt } from "../adapt";
|
|
|
2
2
|
import type {
|
|
3
3
|
AgentWireAttachment,
|
|
4
4
|
AgentWireMessage,
|
|
5
|
+
AgentWireToolResult,
|
|
5
6
|
LlmAccepts,
|
|
6
7
|
LlmAdaptor,
|
|
7
8
|
LlmLimits,
|
|
@@ -14,12 +15,14 @@ import { LlmOverflow } from "./llmOverflow";
|
|
|
14
15
|
import { eachSseData } from "./sseData";
|
|
15
16
|
|
|
16
17
|
type AnthropicSource = { type: "base64"; media_type: string; data: string } | { type: "url"; url: string };
|
|
17
|
-
type
|
|
18
|
+
type AnthropicContentBlock =
|
|
18
19
|
| { type: "text"; text: string }
|
|
19
20
|
| { type: "image"; source: AnthropicSource }
|
|
20
|
-
| { type: "document"; source: AnthropicSource }
|
|
21
|
+
| { type: "document"; source: AnthropicSource };
|
|
22
|
+
type AnthropicBlock =
|
|
23
|
+
| AnthropicContentBlock
|
|
21
24
|
| { type: "tool_use"; id: string; name: string; input: Record<string, unknown> }
|
|
22
|
-
| { type: "tool_result"; tool_use_id: string; content: string };
|
|
25
|
+
| { type: "tool_result"; tool_use_id: string; content: string | AnthropicContentBlock[] };
|
|
23
26
|
interface AnthropicMessage {
|
|
24
27
|
role: "user" | "assistant";
|
|
25
28
|
content: AnthropicBlock[];
|
|
@@ -76,7 +79,7 @@ export class AnthropicLlm
|
|
|
76
79
|
}
|
|
77
80
|
|
|
78
81
|
async chat(request: LlmTurnRequest, onDelta?: (delta: string) => void): Promise<LlmTurnAnswer | null> {
|
|
79
|
-
const model = this.llmOption.model;
|
|
82
|
+
const model = request.model || this.llmOption.model;
|
|
80
83
|
if (!this.llmOption.apiKey || !model) {
|
|
81
84
|
this.logger.warn(
|
|
82
85
|
"AnthropicLlm needs both apiKey and model — set them with option.setLlm(). Agent turns are unavailable.",
|
|
@@ -221,15 +224,7 @@ export class AnthropicLlm
|
|
|
221
224
|
if (message.role === "tool")
|
|
222
225
|
return {
|
|
223
226
|
role: "user",
|
|
224
|
-
content: (message.toolResults ?? []).map((result) => (
|
|
225
|
-
type: "tool_result" as const,
|
|
226
|
-
tool_use_id: result.id,
|
|
227
|
-
content: JSON.stringify({
|
|
228
|
-
...(result.result !== undefined ? { result: result.result } : {}),
|
|
229
|
-
...(result.changes?.length ? { changes: result.changes } : {}),
|
|
230
|
-
...(result.error ? { error: result.error } : {}),
|
|
231
|
-
}),
|
|
232
|
-
})),
|
|
227
|
+
content: (message.toolResults ?? []).map((result) => AnthropicLlm.toolResult(result, accepts)),
|
|
233
228
|
};
|
|
234
229
|
if (message.role === "assistant")
|
|
235
230
|
return {
|
|
@@ -248,9 +243,36 @@ export class AnthropicLlm
|
|
|
248
243
|
}
|
|
249
244
|
|
|
250
245
|
static userContent(message: AgentWireMessage, accepts?: LlmAccepts): AnthropicBlock[] {
|
|
251
|
-
const attachments = message.attachments ?? [];
|
|
252
246
|
const notes: string[] = [];
|
|
253
|
-
const blocks =
|
|
247
|
+
const blocks = AnthropicLlm.attachmentBlocks(message.attachments ?? [], accepts, notes);
|
|
248
|
+
const text = [message.text, ...notes].filter(Boolean).join("\n\n");
|
|
249
|
+
return [...(text ? [{ type: "text" as const, text }] : []), ...blocks];
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** A string while the call returned no file, so a transcript without one posts what it always did. */
|
|
253
|
+
static toolResult(result: AgentWireToolResult, accepts?: LlmAccepts): AnthropicBlock {
|
|
254
|
+
const payload = JSON.stringify({
|
|
255
|
+
...(result.result !== undefined ? { result: result.result } : {}),
|
|
256
|
+
...(result.changes?.length ? { changes: result.changes } : {}),
|
|
257
|
+
...(result.error ? { error: result.error } : {}),
|
|
258
|
+
});
|
|
259
|
+
if (!result.attachments?.length) return { type: "tool_result", tool_use_id: result.id, content: payload };
|
|
260
|
+
const notes: string[] = [];
|
|
261
|
+
const blocks = AnthropicLlm.attachmentBlocks(result.attachments, accepts, notes);
|
|
262
|
+
return {
|
|
263
|
+
type: "tool_result",
|
|
264
|
+
tool_use_id: result.id,
|
|
265
|
+
content: [{ type: "text", text: [payload, ...notes].join("\n\n") }, ...blocks],
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/** Pushes a note for each file no block can carry, for the caller to fold into the text beside them. */
|
|
270
|
+
static attachmentBlocks(
|
|
271
|
+
attachments: AgentWireAttachment[],
|
|
272
|
+
accepts: LlmAccepts | undefined,
|
|
273
|
+
notes: string[],
|
|
274
|
+
): AnthropicContentBlock[] {
|
|
275
|
+
return attachments.flatMap((attachment): AnthropicContentBlock[] => {
|
|
254
276
|
if (attachment.text)
|
|
255
277
|
return [
|
|
256
278
|
{
|
|
@@ -271,8 +293,6 @@ export class AnthropicLlm
|
|
|
271
293
|
notes.push(`[Attachment not read: ${attachment.name} (${attachment.mimeType}) — this API has no block for it.]`);
|
|
272
294
|
return [];
|
|
273
295
|
});
|
|
274
|
-
const text = [message.text, ...notes].filter(Boolean).join("\n\n");
|
|
275
|
-
return [...(text ? [{ type: "text" as const, text }] : []), ...blocks];
|
|
276
296
|
}
|
|
277
297
|
|
|
278
298
|
static typed(source: AnthropicSource, mimeType: string): AnthropicSource {
|
|
@@ -19,8 +19,10 @@ import {
|
|
|
19
19
|
SearchIndex,
|
|
20
20
|
} from "./searchIndex";
|
|
21
21
|
import { PostgresDialect } from "./sql/dialect/postgres";
|
|
22
|
+
import { SqliteDialect } from "./sql/dialect/sqlite";
|
|
22
23
|
import { BunSqliteClient } from "./sql/driver/bunSqlite";
|
|
23
24
|
import { PostgresAkanClient } from "./sql/driver/postgres";
|
|
25
|
+
import { MigrationTables } from "./sql/MigrationTables";
|
|
24
26
|
import { PendingStoreEnsures } from "./sql/PendingStoreEnsures";
|
|
25
27
|
import { PostgresInsightSession } from "./sql/PostgresInsightSession";
|
|
26
28
|
import { SqlDocumentStore } from "./sql/SqlDocumentStore";
|
|
@@ -41,6 +43,13 @@ import { defaultSqliteFile } from "./sqlitePath";
|
|
|
41
43
|
|
|
42
44
|
export { PostgresDialect } from "./sql/dialect/postgres";
|
|
43
45
|
export { SqliteDialect } from "./sql/dialect/sqlite";
|
|
46
|
+
export { type MigrationLedgerTable, MigrationTables } from "./sql/MigrationTables";
|
|
47
|
+
export {
|
|
48
|
+
RawDocumentTable,
|
|
49
|
+
type RawFilter,
|
|
50
|
+
type RawFilterOperators,
|
|
51
|
+
type RawFindOptions,
|
|
52
|
+
} from "./sql/RawDocumentTable";
|
|
44
53
|
export { SqlDocumentStore } from "./sql/SqlDocumentStore";
|
|
45
54
|
export type {
|
|
46
55
|
AkanSqlClient,
|
|
@@ -55,8 +64,10 @@ export type {
|
|
|
55
64
|
SqlDialect,
|
|
56
65
|
SqliteDatabaseConfig,
|
|
57
66
|
SqlResultRows,
|
|
67
|
+
TransferRow,
|
|
58
68
|
UpsertByIdOptions,
|
|
59
69
|
} from "./sql/types";
|
|
70
|
+
export { descriptorHash, stableJson } from "./sql/values";
|
|
60
71
|
|
|
61
72
|
const searchConfigOf = (env: SqliteEnv): Required<SearchConfig> => ({
|
|
62
73
|
enabled: env.database?.search?.enabled ?? parseSearchEnabled(process.env.AKAN_SEARCH_ENABLED),
|
|
@@ -87,6 +98,7 @@ export class SqliteDatabase
|
|
|
87
98
|
}))
|
|
88
99
|
implements DatabaseAdaptor
|
|
89
100
|
{
|
|
101
|
+
readonly dialect = new SqliteDialect();
|
|
90
102
|
#db!: Database;
|
|
91
103
|
#client!: BunSqliteClient;
|
|
92
104
|
#stores = new Map<string, SqlDocumentStore>();
|
|
@@ -111,6 +123,7 @@ export class SqliteDatabase
|
|
|
111
123
|
this.#db.run(
|
|
112
124
|
`CREATE TABLE IF NOT EXISTS "_akan_meta" ("key" TEXT PRIMARY KEY NOT NULL, "value" TEXT NOT NULL, "updatedAt" INTEGER NOT NULL)`,
|
|
113
125
|
);
|
|
126
|
+
for (const statement of MigrationTables.schema(this.dialect)) this.#db.run(statement);
|
|
114
127
|
this.#searchIndex = new SearchIndex(this, this.config.search);
|
|
115
128
|
await this.#searchIndex.ensureSchema();
|
|
116
129
|
this.scheduler.registerCron(OPTIMIZE_CRON_KEY, OPTIMIZE_CRON, async () => {
|
|
@@ -246,6 +259,7 @@ export class PostgresDatabase
|
|
|
246
259
|
}))
|
|
247
260
|
implements DatabaseAdaptor
|
|
248
261
|
{
|
|
262
|
+
readonly dialect = new PostgresDialect();
|
|
249
263
|
#sql!: Sql;
|
|
250
264
|
#client!: PostgresAkanClient;
|
|
251
265
|
#stores = new Map<string, SqlDocumentStore>();
|
|
@@ -278,6 +292,7 @@ export class PostgresDatabase
|
|
|
278
292
|
await this.getConnection().execute(
|
|
279
293
|
`CREATE TABLE IF NOT EXISTS "_akan_meta" ("key" TEXT PRIMARY KEY NOT NULL, "value" TEXT NOT NULL, "updatedAt" BIGINT NOT NULL)`,
|
|
280
294
|
);
|
|
295
|
+
for (const statement of MigrationTables.schema(this.dialect)) await this.getConnection().execute(statement);
|
|
281
296
|
await this.getConnection().execute(PostgresDialect.schemaSetup());
|
|
282
297
|
await this.#grantInsightSchema();
|
|
283
298
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mkdir, readdir } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { Logger } from "akanjs/common";
|
|
4
|
+
import { type MigrationLedgerTable, MigrationTables } from "./sql/MigrationTables";
|
|
4
5
|
import type { DatabaseAdaptor, TransferRow } from "./sql/types";
|
|
5
6
|
|
|
6
7
|
export interface TransferReport {
|
|
@@ -11,6 +12,7 @@ export interface TransferReport {
|
|
|
11
12
|
/**
|
|
12
13
|
* Model tables to one NDJSON file each and back, rows as stored. `_akan_meta`, the search mirror, the cache and the
|
|
13
14
|
* queue stay behind: the target writes its own meta and rebuilds the mirror; sessions and pending jobs do not move.
|
|
15
|
+
* The migration ledger moves with the rows, or the target would run again the scripts its data already went through.
|
|
14
16
|
*/
|
|
15
17
|
export class DocumentTransfer {
|
|
16
18
|
static readonly #chunk = 1000;
|
|
@@ -39,9 +41,35 @@ export class DocumentTransfer {
|
|
|
39
41
|
await writer.end();
|
|
40
42
|
reports.push({ table: store.table, rows });
|
|
41
43
|
}
|
|
44
|
+
for (const table of MigrationTables.ledger) {
|
|
45
|
+
const report = await this.#exportLedger(dir, table);
|
|
46
|
+
if (report) reports.push(report);
|
|
47
|
+
}
|
|
42
48
|
return reports;
|
|
43
49
|
}
|
|
44
50
|
|
|
51
|
+
async #exportLedger(dir: string, table: MigrationLedgerTable): Promise<TransferReport | null> {
|
|
52
|
+
let writer: Bun.FileSink | null = null;
|
|
53
|
+
let rows = 0;
|
|
54
|
+
let after: Record<string, unknown> | null = null;
|
|
55
|
+
for (;;) {
|
|
56
|
+
const chunk = await MigrationTables.exportRows(
|
|
57
|
+
this.#database.getConnection(),
|
|
58
|
+
table,
|
|
59
|
+
after,
|
|
60
|
+
DocumentTransfer.#chunk,
|
|
61
|
+
);
|
|
62
|
+
if (chunk.length) writer ??= Bun.file(path.join(dir, `${table.name}.ndjson`)).writer();
|
|
63
|
+
for (const row of chunk) writer?.write(`${JSON.stringify(row)}\n`);
|
|
64
|
+
rows += chunk.length;
|
|
65
|
+
const last = chunk.at(-1);
|
|
66
|
+
if (!last || chunk.length < DocumentTransfer.#chunk) break;
|
|
67
|
+
after = last;
|
|
68
|
+
}
|
|
69
|
+
await writer?.end();
|
|
70
|
+
return writer ? { table: table.name, rows } : null;
|
|
71
|
+
}
|
|
72
|
+
|
|
45
73
|
async importFrom(dir: string): Promise<TransferReport[]> {
|
|
46
74
|
const files = new Set((await readdir(dir)).filter((file) => file.endsWith(".ndjson")));
|
|
47
75
|
const search = this.#database.getSearchIndex();
|
|
@@ -66,10 +94,32 @@ export class DocumentTransfer {
|
|
|
66
94
|
this.#logger.warn(`Another process holds the search rebuild of ${store.table}; it catches up once that ends`);
|
|
67
95
|
reports.push({ table: store.table, rows });
|
|
68
96
|
}
|
|
97
|
+
for (const table of MigrationTables.ledger) {
|
|
98
|
+
const file = `${table.name}.ndjson`;
|
|
99
|
+
if (files.delete(file)) reports.push(await this.#importLedger(path.join(dir, file), table));
|
|
100
|
+
}
|
|
69
101
|
for (const file of files) this.#logger.warn(`${file} matches no model of this app; skipped`);
|
|
70
102
|
return reports;
|
|
71
103
|
}
|
|
72
104
|
|
|
105
|
+
async #importLedger(file: string, table: MigrationLedgerTable): Promise<TransferReport> {
|
|
106
|
+
const write = async (chunk: Record<string, unknown>[]) =>
|
|
107
|
+
await this.#database.transaction(
|
|
108
|
+
async () => await MigrationTables.importRows(this.#database.getConnection(), table, chunk),
|
|
109
|
+
);
|
|
110
|
+
let rows = 0;
|
|
111
|
+
let chunk: Record<string, unknown>[] = [];
|
|
112
|
+
for await (const line of DocumentTransfer.#lines(file)) {
|
|
113
|
+
chunk.push(JSON.parse(line) as Record<string, unknown>);
|
|
114
|
+
if (chunk.length < DocumentTransfer.#chunk) continue;
|
|
115
|
+
await write(chunk);
|
|
116
|
+
rows += chunk.length;
|
|
117
|
+
chunk = [];
|
|
118
|
+
}
|
|
119
|
+
if (chunk.length) await write(chunk);
|
|
120
|
+
return { table: table.name, rows: rows + chunk.length };
|
|
121
|
+
}
|
|
122
|
+
|
|
73
123
|
#stores() {
|
|
74
124
|
const stores = this.#database.stores?.();
|
|
75
125
|
if (!stores) throw new Error("This database adaptor keeps no model stores to transfer.");
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { adapt } from "../adapt";
|
|
2
|
+
import { EndpointCacheKeys } from "../endpointCacheKeys";
|
|
3
|
+
import { CacheAdaptorRole } from "./role.adaptor";
|
|
4
|
+
|
|
5
|
+
/** Drops an endpoint's `{ cache }` answers before their TTL, across instances: every entry, or the one for `args`. */
|
|
6
|
+
export class EndpointCacheControl extends adapt("endpointCacheControl", ({ plug }) => ({
|
|
7
|
+
cache: plug(CacheAdaptorRole),
|
|
8
|
+
})) {
|
|
9
|
+
/** `args`: every declared argument in order, `null` for an omitted search one; not for slice lists. */
|
|
10
|
+
async invalidate(endpoint: string, args?: unknown[]): Promise<boolean> {
|
|
11
|
+
try {
|
|
12
|
+
await EndpointCacheKeys.invalidate(this.cache, endpoint, args);
|
|
13
|
+
return true;
|
|
14
|
+
} catch (error) {
|
|
15
|
+
this.logger.error(`Cache invalidation failed for ${endpoint}: ${String(error)}`);
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -3,6 +3,7 @@ export * from "./cache.adaptor";
|
|
|
3
3
|
export * from "./compress.adaptor";
|
|
4
4
|
export * from "./database.adaptor";
|
|
5
5
|
export * from "./documentTransfer";
|
|
6
|
+
export * from "./endpointCacheControl.adaptor";
|
|
6
7
|
export * from "./insightQuery";
|
|
7
8
|
export * from "./llm.adaptor";
|
|
8
9
|
export * from "./llmOverflow";
|
|
@@ -10,6 +10,8 @@ export interface AgentWireToolResult {
|
|
|
10
10
|
result?: unknown;
|
|
11
11
|
changes?: unknown[];
|
|
12
12
|
error?: string;
|
|
13
|
+
/** Files the call handed the model, as content beside the JSON; one this model cannot read arrives as a `text` note. */
|
|
14
|
+
attachments?: AgentWireAttachment[];
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
/** Exactly one carrier reaches the model: `data` (inlined bytes), `url` (fetched by the provider) or `text`. */
|
|
@@ -68,6 +70,11 @@ export interface LlmTurnRequest {
|
|
|
68
70
|
tools: AgentWireTool[];
|
|
69
71
|
context: AgentWireContext[];
|
|
70
72
|
instructions?: string;
|
|
73
|
+
/**
|
|
74
|
+
* This turn's model in place of `LlmOption.model`. `accepts`, `maxTokens` and `contextWindow` stay the option's, so a
|
|
75
|
+
* model that differs in them needs an adaptor of its own. Set by server code only: `runAgentTurn` takes no model.
|
|
76
|
+
*/
|
|
77
|
+
model?: string;
|
|
71
78
|
}
|
|
72
79
|
|
|
73
80
|
export interface LlmTurnAnswer {
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
AgentWireAttachment,
|
|
3
|
+
AgentWireMessage,
|
|
4
|
+
LlmAccepts,
|
|
5
|
+
LlmTurnAnswer,
|
|
6
|
+
LlmTurnRequest,
|
|
7
|
+
LlmUsage,
|
|
8
|
+
} from "./llm.adaptor";
|
|
2
9
|
import { eachSseData } from "./sseData";
|
|
3
10
|
|
|
4
11
|
export interface OpenaiToolCall {
|
|
@@ -25,7 +32,8 @@ interface OpenaiStreamChunk {
|
|
|
25
32
|
finish_reason?: string | null;
|
|
26
33
|
}[];
|
|
27
34
|
}
|
|
28
|
-
type
|
|
35
|
+
type OpenaiImagePart = { type: "image_url"; image_url: { url: string } };
|
|
36
|
+
type OpenaiContentPart = { type: "text"; text: string } | OpenaiImagePart;
|
|
29
37
|
export interface OpenaiMessage {
|
|
30
38
|
role: "system" | "user" | "assistant" | "tool";
|
|
31
39
|
content: string | OpenaiContentPart[];
|
|
@@ -86,16 +94,7 @@ export class OpenaiDialect {
|
|
|
86
94
|
content: `Summary of the earlier conversation, standing in for the messages it replaced:\n\n${message.text ?? ""}`,
|
|
87
95
|
},
|
|
88
96
|
];
|
|
89
|
-
if (message.role === "tool")
|
|
90
|
-
return (message.toolResults ?? []).map((result) => ({
|
|
91
|
-
role: "tool" as const,
|
|
92
|
-
tool_call_id: result.id,
|
|
93
|
-
content: JSON.stringify({
|
|
94
|
-
...(result.result !== undefined ? { result: result.result } : {}),
|
|
95
|
-
...(result.changes?.length ? { changes: result.changes } : {}),
|
|
96
|
-
...(result.error ? { error: result.error } : {}),
|
|
97
|
-
}),
|
|
98
|
-
}));
|
|
97
|
+
if (message.role === "tool") return OpenaiDialect.toolMessages(message, accepts);
|
|
99
98
|
if (message.role === "assistant")
|
|
100
99
|
return [
|
|
101
100
|
{
|
|
@@ -116,8 +115,47 @@ export class OpenaiDialect {
|
|
|
116
115
|
}
|
|
117
116
|
|
|
118
117
|
static userContent(message: AgentWireMessage, accepts?: LlmAccepts): string | OpenaiContentPart[] {
|
|
119
|
-
const attachments = message.attachments ?? [];
|
|
120
118
|
const notes: string[] = [];
|
|
119
|
+
const { blocks, images } = OpenaiDialect.attachmentParts(message.attachments ?? [], accepts, notes);
|
|
120
|
+
const text = [message.text, ...blocks, ...notes].filter(Boolean).join("\n\n");
|
|
121
|
+
if (!images.length) return text;
|
|
122
|
+
return [...(text ? [{ type: "text" as const, text }] : []), ...images.map(({ part }) => part)];
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
static readonly toolPicturesHeading =
|
|
126
|
+
"Pictures the tool calls above returned, each after the name of the call that returned it. They are content, not something the user said.";
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* A `tool` message carries text alone in this dialect, so the pictures a call returned follow every tool message
|
|
130
|
+
* of the turn in one user message: between two tool messages it would break the run each call's answer has to sit in.
|
|
131
|
+
*/
|
|
132
|
+
static toolMessages(message: AgentWireMessage, accepts?: LlmAccepts): OpenaiMessage[] {
|
|
133
|
+
const shown: OpenaiContentPart[] = [];
|
|
134
|
+
const answers = (message.toolResults ?? []).map((result): OpenaiMessage => {
|
|
135
|
+
const payload = JSON.stringify({
|
|
136
|
+
...(result.result !== undefined ? { result: result.result } : {}),
|
|
137
|
+
...(result.changes?.length ? { changes: result.changes } : {}),
|
|
138
|
+
...(result.error ? { error: result.error } : {}),
|
|
139
|
+
});
|
|
140
|
+
const notes: string[] = [];
|
|
141
|
+
const { blocks, images } = OpenaiDialect.attachmentParts(result.attachments ?? [], accepts, notes);
|
|
142
|
+
for (const { name, part } of images)
|
|
143
|
+
shown.push({ type: "text", text: `[${result.name} returned ${name}]` }, part);
|
|
144
|
+
return { role: "tool", tool_call_id: result.id, content: [payload, ...blocks, ...notes].join("\n\n") };
|
|
145
|
+
});
|
|
146
|
+
if (!shown.length) return answers;
|
|
147
|
+
return [
|
|
148
|
+
...answers,
|
|
149
|
+
{ role: "user", content: [{ type: "text", text: OpenaiDialect.toolPicturesHeading }, ...shown] },
|
|
150
|
+
];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Pushes a note for each file no part can carry, for the caller to fold into the text beside them. */
|
|
154
|
+
static attachmentParts(
|
|
155
|
+
attachments: AgentWireAttachment[],
|
|
156
|
+
accepts: LlmAccepts | undefined,
|
|
157
|
+
notes: string[],
|
|
158
|
+
): { blocks: string[]; images: { name: string; part: OpenaiImagePart }[] } {
|
|
121
159
|
|
|
122
160
|
const blocks = attachments.flatMap((attachment) =>
|
|
123
161
|
attachment.text ? [`--- attachment: ${attachment.name} (${attachment.mimeType}) ---\n${attachment.text}`] : [],
|
|
@@ -138,11 +176,9 @@ export class OpenaiDialect {
|
|
|
138
176
|
}
|
|
139
177
|
|
|
140
178
|
const url = attachment.data ? `data:${mimeType};base64,${attachment.data}` : (attachment.url ?? "");
|
|
141
|
-
return url ? [{ type: "image_url" as const, image_url: { url } }] : [];
|
|
179
|
+
return url ? [{ name: attachment.name, part: { type: "image_url" as const, image_url: { url } } }] : [];
|
|
142
180
|
});
|
|
143
|
-
|
|
144
|
-
if (!images.length) return text;
|
|
145
|
-
return [...(text ? [{ type: "text" as const, text }] : []), ...images];
|
|
181
|
+
return { blocks, images };
|
|
146
182
|
}
|
|
147
183
|
|
|
148
184
|
static async consumeStream(
|
|
@@ -31,7 +31,7 @@ export class OpenaiLlm
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
async chat(request: LlmTurnRequest, onDelta?: (delta: string) => void): Promise<LlmTurnAnswer | null> {
|
|
34
|
-
const model = this.llmOption.model;
|
|
34
|
+
const model = request.model || this.llmOption.model;
|
|
35
35
|
if (!this.llmOption.apiKey || !model) {
|
|
36
36
|
this.logger.warn(
|
|
37
37
|
"OpenaiLlm needs both apiKey and model — set them with option.setLlm(). Agent turns are unavailable.",
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { AkanSqlClient, SqlDialect } from "./types";
|
|
2
|
+
import { quoteIdent } from "./values";
|
|
3
|
+
|
|
4
|
+
export interface MigrationLedgerTable {
|
|
5
|
+
name: string;
|
|
6
|
+
key: readonly string[];
|
|
7
|
+
columns: readonly string[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** The data-migration ledger, kept beside the rows it describes so each environment records what was applied to it. */
|
|
11
|
+
export class MigrationTables {
|
|
12
|
+
static readonly run = "_akan_migration_run";
|
|
13
|
+
static readonly change = "_akan_migration_change";
|
|
14
|
+
static readonly ledger: readonly MigrationLedgerTable[] = [
|
|
15
|
+
{
|
|
16
|
+
name: MigrationTables.run,
|
|
17
|
+
key: ["id"],
|
|
18
|
+
columns: [
|
|
19
|
+
"id",
|
|
20
|
+
"migrationId",
|
|
21
|
+
"kind",
|
|
22
|
+
"status",
|
|
23
|
+
"target",
|
|
24
|
+
"checksum",
|
|
25
|
+
"buildId",
|
|
26
|
+
"params",
|
|
27
|
+
"planHash",
|
|
28
|
+
"summary",
|
|
29
|
+
"actor",
|
|
30
|
+
"checkpoint",
|
|
31
|
+
"startedAt",
|
|
32
|
+
"finishedAt",
|
|
33
|
+
"error",
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: MigrationTables.change,
|
|
38
|
+
key: ["runId", "seq"],
|
|
39
|
+
columns: ["runId", "seq", "tableName", "docId", "op", "before", "after"],
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
static schema(dialect: Pick<SqlDialect, "timestampType">) {
|
|
44
|
+
const ts = dialect.timestampType();
|
|
45
|
+
const run = quoteIdent(MigrationTables.run);
|
|
46
|
+
return [
|
|
47
|
+
`CREATE TABLE IF NOT EXISTS ${run} ("id" TEXT PRIMARY KEY NOT NULL, "migrationId" TEXT NOT NULL, "kind" TEXT NOT NULL, "status" TEXT NOT NULL, "target" TEXT, "checksum" TEXT NOT NULL, "buildId" TEXT, "params" TEXT, "planHash" TEXT, "summary" TEXT, "actor" TEXT, "checkpoint" TEXT, "startedAt" ${ts} NOT NULL, "finishedAt" ${ts}, "error" TEXT)`,
|
|
48
|
+
`CREATE INDEX IF NOT EXISTS ${quoteIdent(`${MigrationTables.run}_migrationId`)} ON ${run} ("migrationId", "startedAt")`,
|
|
49
|
+
`CREATE TABLE IF NOT EXISTS ${quoteIdent(MigrationTables.change)} ("runId" TEXT NOT NULL, "seq" INTEGER NOT NULL, "tableName" TEXT NOT NULL, "docId" TEXT NOT NULL, "op" TEXT NOT NULL, "before" TEXT NOT NULL, "after" TEXT NOT NULL, PRIMARY KEY ("runId", "seq"))`,
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Up to `limit` rows after the key of `after`, in key order. */
|
|
54
|
+
static async exportRows(
|
|
55
|
+
client: AkanSqlClient,
|
|
56
|
+
table: MigrationLedgerTable,
|
|
57
|
+
after: Record<string, unknown> | null,
|
|
58
|
+
limit: number,
|
|
59
|
+
) {
|
|
60
|
+
const keyset = MigrationTables.#after(table, after);
|
|
61
|
+
return await client
|
|
62
|
+
.prepare(
|
|
63
|
+
`SELECT ${table.columns.map(quoteIdent).join(", ")} FROM ${quoteIdent(table.name)} WHERE ${keyset.sql} ORDER BY ${table.key.map(quoteIdent).join(", ")} LIMIT ${Math.trunc(limit)}`,
|
|
64
|
+
)
|
|
65
|
+
.all<Record<string, unknown>>(...keyset.params);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static async importRows(client: AkanSqlClient, table: MigrationLedgerTable, rows: Record<string, unknown>[]) {
|
|
69
|
+
const columns = table.columns.map(quoteIdent);
|
|
70
|
+
const updates = table.columns
|
|
71
|
+
.filter((column) => !table.key.includes(column))
|
|
72
|
+
.map((column) => `${quoteIdent(column)} = excluded.${quoteIdent(column)}`);
|
|
73
|
+
const statement = client.prepare(
|
|
74
|
+
`INSERT INTO ${quoteIdent(table.name)} (${columns.join(", ")}) VALUES (${columns.map(() => "?").join(", ")}) ON CONFLICT (${table.key.map(quoteIdent).join(", ")}) DO UPDATE SET ${updates.join(", ")}`,
|
|
75
|
+
);
|
|
76
|
+
for (const row of rows) await statement.run(...table.columns.map((column) => row[column] ?? null));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
static #after(table: MigrationLedgerTable, after: Record<string, unknown> | null) {
|
|
80
|
+
if (!after) return { sql: "1 = 1", params: [] as unknown[] };
|
|
81
|
+
const terms = table.key.map((column, idx) => {
|
|
82
|
+
const equal = table.key.slice(0, idx);
|
|
83
|
+
return {
|
|
84
|
+
sql: `(${[...equal.map((prefix) => `${quoteIdent(prefix)} = ?`), `${quoteIdent(column)} > ?`].join(" AND ")})`,
|
|
85
|
+
params: [...equal.map((prefix) => after[prefix]), after[column]],
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
return { sql: `(${terms.map((term) => term.sql).join(" OR ")})`, params: terms.flatMap((term) => term.params) };
|
|
89
|
+
}
|
|
90
|
+
}
|