akanjs 3.0.0-alpha.7 → 3.0.0-alpha.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +103 -0
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/base/baseEnv.ts +7 -4
- package/base/primitiveRegistry.ts +59 -12
- package/base/symbols.ts +4 -0
- package/client/capacitor.ts +34 -0
- package/client/clientRuntime.ts +5 -0
- package/client/csrTypes.ts +4 -3
- package/client/index.ts +1 -0
- package/client/locale.ts +2 -2
- package/client/router.ts +7 -7
- package/client/sharedContext.ts +31 -0
- package/client/translator.ts +2 -2
- package/client/types.ts +3 -3
- package/common/Logger.ts +280 -67
- package/common/clientAddress.ts +40 -0
- package/common/deepObjectify.ts +24 -9
- package/common/index.ts +42 -1
- package/common/logContext.ts +27 -0
- package/common/mcpExposure.ts +114 -0
- package/common/pathGetLoose.ts +31 -0
- package/common/pathSet.ts +17 -5
- package/common/plainFieldsOf.ts +13 -0
- package/common/routeConvention.ts +22 -12
- package/common/websocketBinaryFrame.ts +46 -0
- package/constant/crystalize.ts +94 -28
- package/constant/dateSlot.ts +62 -0
- package/constant/deserialize.ts +3 -2
- package/constant/fieldInfo.ts +43 -3
- package/constant/fieldQueryMeta.ts +35 -0
- package/constant/getDefault.ts +16 -11
- package/constant/hydrationPlan.ts +72 -0
- package/constant/immerify.ts +4 -6
- package/constant/index.ts +5 -0
- package/constant/labelOf.ts +26 -0
- package/constant/mask.ts +67 -0
- package/constant/purify.ts +17 -11
- package/constant/textFieldPaths.ts +13 -7
- package/constant/types.ts +19 -13
- package/constant/via.ts +24 -17
- package/dictionary/DictionaryLookup.ts +30 -0
- package/dictionary/agent.dictionary.ts +31 -0
- package/dictionary/agentTurn.dictionary.ts +29 -0
- package/dictionary/base.dictionary.ts +81 -0
- package/dictionary/dictInfo.ts +11 -2
- package/dictionary/dictionary.ts +9 -3
- package/dictionary/index.ts +1 -0
- package/dictionary/trans.ts +2 -2
- package/document/documentQuery.ts +1 -0
- package/document/filterMeta.ts +77 -12
- package/document/index.ts +1 -0
- package/document/noDocumentError.ts +12 -0
- package/document/types.ts +0 -1
- package/fetch/agentTurn.ts +19 -0
- package/fetch/client/fetchClient.ts +137 -37
- package/fetch/client/httpClient.ts +95 -20
- package/fetch/client/wsClient.ts +27 -12
- package/fetch/fetchType/appliedReturn.type.ts +65 -44
- package/fetch/fetchType/endpointFetch.type.ts +17 -8
- package/fetch/fetchType/sliceFetch.type.ts +27 -50
- package/fetch/index.ts +1 -0
- package/index.ts +80 -6
- package/local/apps/akan/akan-local.db +0 -0
- package/local/apps/akan/akan-local.db-shm +0 -0
- package/local/apps/akan/akan-local.db-wal +0 -0
- package/local/apps/akan/akan-local_solid.db +0 -0
- package/local/apps/akan/akan-local_solid.db-shm +0 -0
- package/local/apps/akan/akan-local_solid.db-wal +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local.db +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local.db-shm +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local.db-wal +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local_solid.db +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-shm +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-wal +0 -0
- package/package.json +27 -18
- package/server/akanApp.ts +278 -138
- package/server/akanAppHeaders.ts +16 -2
- package/server/akanOption.ts +63 -8
- package/server/akanServer.ts +387 -32
- package/server/animatedImage.ts +83 -0
- package/server/assetEncoding.ts +4 -24
- package/server/binaryPubsub.ts +55 -0
- package/server/console.ts +110 -101
- package/server/consoleEvaluator.ts +51 -0
- package/server/consolePasteFilter.ts +91 -0
- package/server/consoleSession.ts +242 -0
- package/server/contentEncoding.ts +83 -0
- package/server/devtools/signalSerializer.ts +2 -2
- package/server/devtools/types.ts +4 -4
- package/server/di/diLifecycle.ts +123 -13
- package/server/di/predefinedAdaptor.ts +6 -0
- package/server/di/utils.ts +40 -0
- package/server/imageOptimizer.ts +154 -57
- package/server/lifecycle/runtimeDir.ts +14 -0
- package/server/lifecycle/shutdownManager.ts +1 -1
- package/server/logging/childOutputReader.ts +137 -0
- package/server/logging/hubFileSink.ts +39 -0
- package/server/logging/logControlSocket.ts +173 -0
- package/server/logging/logForwarder.ts +131 -0
- package/server/logging/logHub.ts +0 -0
- package/server/logging/logQuery.ts +130 -0
- package/server/logging/logStdoutWriter.ts +39 -0
- package/server/logging/logStreamRoute.ts +87 -0
- package/server/logging/logTailClient.ts +161 -0
- package/server/mcp/McpAuth.ts +177 -0
- package/server/mcp/McpDispatcher.ts +289 -0
- package/server/mcp/McpEventStream.ts +24 -0
- package/server/mcp/McpExecutionContext.ts +105 -0
- package/server/mcp/McpRouter.ts +621 -0
- package/server/mcp/index.ts +5 -0
- package/server/processMetricsCollector.ts +1 -1
- package/server/resolver/database.resolver.ts +5 -4
- package/server/resolver/signal.resolver.ts +208 -86
- package/server/routeTreeBuilder.ts +10 -8
- package/server/routing/apiRouter.ts +44 -14
- package/server/routing/appWsData.ts +24 -2
- package/server/routing/eventStream.ts +93 -0
- package/server/routing/soloAppRoutes.ts +50 -0
- package/server/rscWorker.tsx +36 -22
- package/server/rscWorkerHost.ts +59 -8
- package/server/semaphore.ts +22 -0
- package/server/subRouteIndexDocument.tsx +61 -0
- package/server/systemPageDocument.tsx +3 -3
- package/server/systemPages.tsx +49 -16
- package/server/types.tsx +28 -0
- package/server/vendor/akanjs-fetch.ts +1 -0
- package/server/webRouter.ts +96 -39
- package/service/adapt.ts +4 -4
- package/service/agent.service.ts +81 -0
- package/service/base.service.ts +2 -1
- package/service/index.ts +1 -0
- package/service/injectInfo.ts +8 -3
- package/service/ipcTypes.ts +6 -0
- package/service/predefinedAdaptor/compress.adaptor.ts +5 -1
- package/service/predefinedAdaptor/database.adaptor.ts +68 -37
- package/service/predefinedAdaptor/deepseekLlm.ts +271 -0
- package/service/predefinedAdaptor/index.ts +3 -0
- package/service/predefinedAdaptor/insightQuery.ts +183 -0
- package/service/predefinedAdaptor/llm.adaptor.ts +115 -0
- package/service/predefinedAdaptor/logging.adaptor.ts +1 -1
- package/service/predefinedAdaptor/queue.adaptor.ts +5 -2
- package/service/predefinedAdaptor/role.adaptor.ts +2 -0
- package/service/predefinedAdaptor/schedule.adaptor.ts +12 -5
- package/service/predefinedAdaptor/solidPubsub.adaptor.ts +10 -6
- package/service/predefinedAdaptor/solidQueue.adaptor.ts +6 -2
- package/service/predefinedAdaptor/solidSqlite.ts +11 -9
- package/service/predefinedAdaptor/websocket.adaptor.ts +6 -1
- package/service/serve.ts +16 -9
- package/service/toolNames.ts +119 -0
- package/signal/agent/AgentCatalogue.ts +165 -0
- package/signal/agent/index.ts +1 -0
- package/signal/agent.signal.ts +38 -0
- package/signal/agentTurn.ts +8 -0
- package/signal/agentTurnStream.ts +60 -0
- package/signal/base.signal.ts +2 -1
- package/signal/endpointInfo.ts +38 -2
- package/signal/guard.ts +28 -1
- package/signal/guards.ts +49 -1
- package/signal/index.ts +6 -0
- package/signal/intercept.ts +4 -4
- package/signal/internalArg.ts +21 -4
- package/signal/mcp/McpDocument.ts +326 -0
- package/signal/mcp/McpProgress.ts +106 -0
- package/signal/mcp/McpUriTemplate.ts +80 -0
- package/signal/mcp/Msg.ts +368 -0
- package/signal/mcp/index.ts +5 -0
- package/signal/mcp/mcpProtocol.ts +120 -0
- package/signal/middleware.ts +3 -3
- package/signal/openapi/openapi.ts +36 -173
- package/signal/schema/JsonSchemaBuilder.ts +221 -0
- package/signal/schema/index.ts +1 -0
- package/signal/serializer/fetch.serializer.ts +51 -0
- package/signal/signalContext.ts +324 -76
- package/signal/slice.ts +62 -27
- package/signal/trace.ts +268 -9
- package/signal/types.ts +55 -4
- package/store/action.ts +34 -41
- package/store/actionTag.ts +33 -0
- package/store/agent/AgentBridge.ts +87 -0
- package/store/agent/AgentContext.ts +71 -0
- package/store/agent/AgentPrompts.ts +111 -0
- package/store/agent/ScreenReader.ts +349 -0
- package/store/agent/ScreenSettle.ts +45 -0
- package/store/agent/ScreenTarget.ts +135 -0
- package/store/agent/StoreCatalogue.ts +116 -0
- package/store/agent/StoreSurfaceSource.ts +225 -0
- package/store/agent/index.ts +13 -0
- package/store/agent/storeSurface.ts +28 -0
- package/store/agent/types.ts +16 -0
- package/store/agentic/AgentValue.ts +119 -0
- package/store/agentic/StExposeBuilder.ts +47 -0
- package/store/agentic/StExposeDraft.ts +24 -0
- package/store/agentic/StStateBuilder.ts +85 -0
- package/store/agentic/StStateDraft.ts +23 -0
- package/store/agentic/StToolBuilder.ts +279 -0
- package/store/agentic/StToolDraft.ts +22 -0
- package/store/agentic/attachAgentic.ts +33 -0
- package/store/agentic/formFields.ts +194 -0
- package/store/agentic/index.ts +12 -0
- package/store/agentic/useFieldTool.ts +183 -0
- package/store/agentic/useFormTools.ts +77 -0
- package/store/agentic/useRelationFieldTool.ts +113 -0
- package/store/baseSt.ts +1 -1
- package/store/databaseStateNames.ts +31 -0
- package/store/formSetterNames.ts +35 -0
- package/store/index.ts +8 -0
- package/store/rootStore.ts +3 -1
- package/store/sliceRole.ts +36 -0
- package/store/state.ts +2 -12
- package/store/store.ts +9 -0
- package/store/storeInstance.ts +185 -20
- package/store/storeRegistry.ts +39 -1
- package/store/types.ts +5 -0
- package/store/withSelector.ts +5 -4
- package/test/index.ts +1 -1
- package/test/registerDom.ts +4 -0
- package/test/sampleOf.ts +2 -0
- package/test/signalTestRuntime.ts +5 -5
- package/test/testServer.ts +14 -11
- package/types/base/baseEnv.d.ts +1 -1
- package/types/base/primitiveRegistry.d.ts +20 -8
- package/types/base/symbols.d.ts +4 -0
- package/types/client/capacitor.d.ts +39 -0
- package/types/client/clientRuntime.d.ts +7 -0
- package/types/client/index.d.ts +1 -0
- package/types/client/sharedContext.d.ts +21 -0
- package/types/client/types.d.ts +5 -3
- package/types/common/Logger.d.ts +88 -6
- package/types/common/clientAddress.d.ts +19 -0
- package/types/common/deepObjectify.d.ts +4 -2
- package/types/common/index.d.ts +8 -2
- package/types/common/logContext.d.ts +17 -0
- package/types/common/mcpExposure.d.ts +64 -0
- package/types/common/pathGetLoose.d.ts +8 -0
- package/types/common/plainFieldsOf.d.ts +6 -0
- package/types/common/routeConvention.d.ts +6 -0
- package/types/common/websocketBinaryFrame.d.ts +17 -0
- package/types/constant/constantRegistry.d.ts +2 -10
- package/types/constant/crystalize.d.ts +5 -0
- package/types/constant/dateSlot.d.ts +14 -0
- package/types/constant/fieldInfo.d.ts +20 -3
- package/types/constant/fieldQueryMeta.d.ts +17 -0
- package/types/constant/getDefault.d.ts +8 -0
- package/types/constant/hydrationPlan.d.ts +24 -0
- package/types/constant/index.d.ts +5 -0
- package/types/constant/labelOf.d.ts +7 -0
- package/types/constant/mask.d.ts +41 -0
- package/types/constant/purify.d.ts +2 -2
- package/types/constant/types.d.ts +5 -5
- package/types/dictionary/DictionaryLookup.d.ts +14 -0
- package/types/dictionary/agent.dictionary.d.ts +1 -0
- package/types/dictionary/agentTurn.dictionary.d.ts +1 -0
- package/types/dictionary/base.dictionary.d.ts +1 -1
- package/types/dictionary/dictInfo.d.ts +7 -1
- package/types/dictionary/dictionary.d.ts +11 -9
- package/types/dictionary/index.d.ts +1 -0
- package/types/document/filterMeta.d.ts +24 -4
- package/types/document/index.d.ts +1 -0
- package/types/document/noDocumentError.d.ts +12 -0
- package/types/document/types.d.ts +0 -1
- package/types/fetch/agentTurn.d.ts +475 -0
- package/types/fetch/client/fetchClient.d.ts +12 -0
- package/types/fetch/client/httpClient.d.ts +2 -1
- package/types/fetch/fetchType/appliedReturn.type.d.ts +37 -18
- package/types/fetch/fetchType/endpointFetch.type.d.ts +8 -5
- package/types/fetch/fetchType/sliceFetch.type.d.ts +11 -15
- package/types/fetch/index.d.ts +1 -0
- package/types/index.d.ts +74 -10
- package/types/server/akanApp.d.ts +12 -0
- package/types/server/akanAppHeaders.d.ts +7 -1
- package/types/server/akanOption.d.ts +36 -6
- package/types/server/akanServer.d.ts +67 -9
- package/types/server/animatedImage.d.ts +7 -0
- package/types/server/assetEncoding.d.ts +1 -1
- package/types/server/binaryPubsub.d.ts +18 -0
- package/types/server/console.d.ts +11 -1
- package/types/server/consoleEvaluator.d.ts +2 -0
- package/types/server/consolePasteFilter.d.ts +11 -0
- package/types/server/consoleSession.d.ts +22 -0
- package/types/server/contentEncoding.d.ts +28 -0
- package/types/server/devtools/types.d.ts +4 -4
- package/types/server/di/diLifecycle.d.ts +10 -2
- package/types/server/di/predefinedAdaptor.d.ts +4 -1
- package/types/server/di/utils.d.ts +16 -0
- package/types/server/lifecycle/runtimeDir.d.ts +5 -0
- package/types/server/logging/childOutputReader.d.ts +40 -0
- package/types/server/logging/hubFileSink.d.ts +18 -0
- package/types/server/logging/logControlSocket.d.ts +60 -0
- package/types/server/logging/logForwarder.d.ts +37 -0
- package/types/server/logging/logHub.d.ts +70 -0
- package/types/server/logging/logQuery.d.ts +31 -0
- package/types/server/logging/logStdoutWriter.d.ts +35 -0
- package/types/server/logging/logStreamRoute.d.ts +20 -0
- package/types/server/logging/logTailClient.d.ts +42 -0
- package/types/server/mcp/McpAuth.d.ts +62 -0
- package/types/server/mcp/McpDispatcher.d.ts +61 -0
- package/types/server/mcp/McpEventStream.d.ts +17 -0
- package/types/server/mcp/McpExecutionContext.d.ts +44 -0
- package/types/server/mcp/McpRouter.d.ts +65 -0
- package/types/server/mcp/index.d.ts +5 -0
- package/types/server/mcp.d.ts +1 -0
- package/types/server/resolver/signal.resolver.d.ts +7 -4
- package/types/server/routing/apiRouter.d.ts +2 -1
- package/types/server/routing/appWsData.d.ts +13 -1
- package/types/server/routing/eventStream.d.ts +23 -0
- package/types/server/routing/soloAppRoutes.d.ts +17 -0
- package/types/server/rscWorkerHost.d.ts +4 -1
- package/types/server/semaphore.d.ts +5 -0
- package/types/server/subRouteIndexDocument.d.ts +8 -0
- package/types/server/systemPageDocument.d.ts +1 -0
- package/types/server/systemPages.d.ts +5 -0
- package/types/server/types.d.ts +16 -0
- package/types/server/vendor/akanjs-fetch.d.ts +1 -0
- package/types/server/webRouter.d.ts +15 -4
- package/types/service/adapt.d.ts +2 -2
- package/types/service/agent.service.d.ts +32 -0
- package/types/service/base.service.d.ts +4 -0
- package/types/service/index.d.ts +1 -0
- package/types/service/injectInfo.d.ts +2 -2
- package/types/service/ipcTypes.d.ts +12 -0
- package/types/service/predefinedAdaptor/compress.adaptor.d.ts +1 -1
- package/types/service/predefinedAdaptor/database.adaptor.d.ts +9 -3
- package/types/service/predefinedAdaptor/deepseekLlm.d.ts +76 -0
- package/types/service/predefinedAdaptor/index.d.ts +3 -0
- package/types/service/predefinedAdaptor/insightQuery.d.ts +50 -0
- package/types/service/predefinedAdaptor/llm.adaptor.d.ts +105 -0
- package/types/service/predefinedAdaptor/queue.adaptor.d.ts +3 -2
- package/types/service/predefinedAdaptor/role.adaptor.d.ts +2 -0
- package/types/service/predefinedAdaptor/schedule.adaptor.d.ts +10 -6
- package/types/service/predefinedAdaptor/solidQueue.adaptor.d.ts +6 -2
- package/types/service/predefinedAdaptor/solidSqlite.d.ts +2 -2
- package/types/service/serve.d.ts +3 -3
- package/types/service/toolNames.d.ts +35 -0
- package/types/signal/agent/AgentCatalogue.d.ts +100 -0
- package/types/signal/agent/index.d.ts +1 -0
- package/types/signal/agent.d.ts +1 -0
- package/types/signal/agent.signal.d.ts +24 -0
- package/types/signal/agentTurn.d.ts +9 -0
- package/types/signal/agentTurnStream.d.ts +24 -0
- package/types/signal/base.signal.d.ts +1 -1
- package/types/signal/endpointInfo.d.ts +21 -3
- package/types/signal/guard.d.ts +12 -0
- package/types/signal/guards.d.ts +23 -1
- package/types/signal/index.d.ts +6 -0
- package/types/signal/intercept.d.ts +2 -2
- package/types/signal/internalArg.d.ts +22 -6
- package/types/signal/mcp/McpDocument.d.ts +84 -0
- package/types/signal/mcp/McpProgress.d.ts +40 -0
- package/types/signal/mcp/McpUriTemplate.d.ts +25 -0
- package/types/signal/mcp/Msg.d.ts +143 -0
- package/types/signal/mcp/index.d.ts +5 -0
- package/types/signal/mcp/mcpProtocol.d.ts +107 -0
- package/types/signal/mcp.d.ts +1 -0
- package/types/signal/middleware.d.ts +7 -7
- package/types/signal/openapi/openapi.d.ts +3 -3
- package/types/signal/schema/JsonSchemaBuilder.d.ts +51 -0
- package/types/signal/schema/index.d.ts +1 -0
- package/types/signal/schema.d.ts +1 -0
- package/types/signal/signalContext.d.ts +67 -8
- package/types/signal/slice.d.ts +42 -15
- package/types/signal/trace.d.ts +52 -2
- package/types/signal/types.d.ts +53 -4
- package/types/store/action.d.ts +7 -5
- package/types/store/actionTag.d.ts +21 -0
- package/types/store/agent/AgentBridge.d.ts +37 -0
- package/types/store/agent/AgentContext.d.ts +16 -0
- package/types/store/agent/AgentPrompts.d.ts +31 -0
- package/types/store/agent/ScreenReader.d.ts +29 -0
- package/types/store/agent/ScreenSettle.d.ts +22 -0
- package/types/store/agent/ScreenTarget.d.ts +34 -0
- package/types/store/agent/StoreCatalogue.d.ts +26 -0
- package/types/store/agent/StoreSurfaceSource.d.ts +30 -0
- package/types/store/agent/index.d.ts +11 -0
- package/types/store/agent/storeSurface.d.ts +14 -0
- package/types/store/agent/types.d.ts +15 -0
- package/types/store/agent.d.ts +1 -0
- package/types/store/agentic/AgentValue.d.ts +43 -0
- package/types/store/agentic/StExposeBuilder.d.ts +21 -0
- package/types/store/agentic/StExposeDraft.d.ts +13 -0
- package/types/store/agentic/StStateBuilder.d.ts +21 -0
- package/types/store/agentic/StStateDraft.d.ts +12 -0
- package/types/store/agentic/StToolBuilder.d.ts +56 -0
- package/types/store/agentic/StToolDraft.d.ts +13 -0
- package/types/store/agentic/attachAgentic.d.ts +25 -0
- package/types/store/agentic/formFields.d.ts +53 -0
- package/types/store/agentic/index.d.ts +12 -0
- package/types/store/agentic/useFieldTool.d.ts +22 -0
- package/types/store/agentic/useFormTools.d.ts +19 -0
- package/types/store/agentic/useRelationFieldTool.d.ts +27 -0
- package/types/store/agentic.d.ts +1 -0
- package/types/store/baseSt.d.ts +35 -39
- package/types/store/databaseStateNames.d.ts +25 -0
- package/types/store/formSetterNames.d.ts +30 -0
- package/types/store/index.d.ts +7 -0
- package/types/store/rootStore.d.ts +5 -1
- package/types/store/sliceRole.d.ts +25 -0
- package/types/store/store.d.ts +5 -1
- package/types/store/storeInstance.d.ts +33 -1
- package/types/store/storeRegistry.d.ts +5 -0
- package/types/store/types.d.ts +4 -0
- package/types/store/withSelector.d.ts +5 -4
- package/types/test/index.d.ts +1 -1
- package/types/test/registerDom.d.ts +1 -0
- package/types/test/signalTestRuntime.d.ts +2 -3
- package/types/test/testServer.d.ts +6 -4
- package/types/ui/Agent/Approval.d.ts +8 -0
- package/types/ui/Agent/Attach.d.ts +16 -0
- package/types/ui/Agent/Bubble.d.ts +26 -0
- package/types/ui/Agent/Chat.d.ts +91 -0
- package/types/ui/Agent/ChatCommands.d.ts +34 -0
- package/types/ui/Agent/Composer.d.ts +23 -0
- package/types/ui/Agent/Context.d.ts +13 -0
- package/types/ui/Agent/Dock.d.ts +17 -0
- package/types/ui/Agent/Guide.d.ts +9 -0
- package/types/ui/Agent/History.d.ts +26 -0
- package/types/ui/Agent/Launcher.d.ts +16 -0
- package/types/ui/Agent/Markdown.d.ts +19 -0
- package/types/ui/Agent/Menu.d.ts +18 -0
- package/types/ui/Agent/Mic.d.ts +8 -0
- package/types/ui/Agent/Question.d.ts +14 -0
- package/types/ui/Agent/Section.d.ts +10 -0
- package/types/ui/Agent/Skip.d.ts +22 -0
- package/types/ui/Agent/StateKey.d.ts +16 -0
- package/types/ui/Agent/Tool.d.ts +15 -0
- package/types/ui/Agent/Transcript.d.ts +13 -0
- package/types/ui/Agent/Zone.d.ts +48 -0
- package/types/ui/Agent/agentSessionOf.d.ts +27 -0
- package/types/ui/Agent/attachment.d.ts +34 -0
- package/types/ui/Agent/fetchRunner.d.ts +12 -0
- package/types/ui/Agent/index.d.ts +19 -0
- package/types/ui/Agent/index_.d.ts +1 -0
- package/types/ui/Agent/markdownBlocks.d.ts +35 -0
- package/types/ui/Agent/markdownSpans.d.ts +2 -0
- package/types/ui/Agent/markdownTable.d.ts +16 -0
- package/types/ui/Agent/sessionHistory.d.ts +14 -0
- package/types/ui/Agent/sessionView.d.ts +15 -0
- package/types/ui/Agent/tokenCount.d.ts +6 -0
- package/types/ui/Agent/useChatAttachments.d.ts +24 -0
- package/types/ui/Agent/useChatVoice.d.ts +30 -0
- package/types/ui/Agent/useDraftRecall.d.ts +14 -0
- package/types/ui/Agent/useKeyboardInset.d.ts +8 -0
- package/types/ui/Agent/useSlashMenu.d.ts +24 -0
- package/types/ui/Agent/voice.d.ts +71 -0
- package/types/ui/Agent.d.ts +1 -0
- package/types/ui/Badge.d.ts +1 -1
- package/types/ui/Button.d.ts +1 -1
- package/types/ui/Constant/Graph.d.ts +10 -0
- package/types/ui/Constant/index.d.ts +2 -1
- package/types/ui/Constant/schemaGraph.d.ts +39 -0
- package/types/ui/Data/Dashboard.d.ts +16 -3
- package/types/ui/Data/Insight.d.ts +1 -1
- package/types/ui/Data/ListContainer.d.ts +15 -7
- package/types/ui/Data/QueryMaker.d.ts +45 -3
- package/types/ui/Data/RefPicker.d.ts +16 -0
- package/types/ui/Data/dataExport.d.ts +5 -0
- package/types/ui/Data/dataText.d.ts +6 -0
- package/types/ui/Data/index.d.ts +2 -0
- package/types/ui/Data/index_.d.ts +1 -0
- package/types/ui/DatePicker.d.ts +15 -11
- package/types/ui/Dialog/LegacyModal.d.ts +13 -0
- package/types/ui/Dialog/Provider.d.ts +3 -1
- package/types/ui/Dialog/context.d.ts +9 -1
- package/types/ui/Dialog/index.d.ts +1 -0
- package/types/ui/DraggableList.d.ts +1 -1
- package/types/ui/Dropdown.d.ts +5 -1
- package/types/ui/Field.d.ts +13 -12
- package/types/ui/Layout/BottomTab.d.ts +3 -2
- package/types/ui/LegacyModal.d.ts +24 -0
- package/types/ui/Loading/ProgressBar.d.ts +4 -0
- package/types/ui/Loading/Spin.d.ts +2 -1
- package/types/ui/Model/AdminPanel.d.ts +15 -3
- package/types/ui/Model/EditModal.d.ts +1 -1
- package/types/ui/Model/New.d.ts +3 -1
- package/types/ui/Model/NewWrapper.d.ts +2 -0
- package/types/ui/Model/NewWrapper_Client.d.ts +2 -1
- package/types/ui/Pagination.d.ts +2 -2
- package/types/ui/Radio.d.ts +1 -1
- package/types/ui/RecentTime.d.ts +18 -1
- package/types/ui/Reference/Collapse.d.ts +11 -0
- package/types/ui/Reference/Panel.d.ts +29 -0
- package/types/ui/Reference/Segmented.d.ts +17 -0
- package/types/ui/Reference/Summary.d.ts +13 -0
- package/types/ui/Reference/Toolbar.d.ts +21 -0
- package/types/ui/Reference/dictText.d.ts +6 -0
- package/types/ui/Reference/index.d.ts +7 -0
- package/types/ui/Reference/style.d.ts +20 -0
- package/types/ui/Reference.d.ts +1 -0
- package/types/ui/ScreenNavigator.d.ts +3 -1
- package/types/ui/Signal/Arg.d.ts +7 -3
- package/types/ui/Signal/Doc.d.ts +4 -6
- package/types/ui/Signal/Object.d.ts +2 -1
- package/types/ui/Signal/RestApi.d.ts +2 -1
- package/types/ui/Signal/WebSocket.d.ts +2 -1
- package/types/ui/Signal/endpointEntries.d.ts +20 -0
- package/types/ui/Signal/style.d.ts +9 -8
- package/types/ui/System/Client.d.ts +1 -2
- package/types/ui/System/Common.d.ts +3 -4
- package/types/ui/System/Messages.d.ts +1 -1
- package/types/ui/Tab/Provider.d.ts +3 -1
- package/types/ui/Tab/context.d.ts +4 -2
- package/types/ui/ToggleSelect.d.ts +1 -0
- package/types/ui/UiOverride/context.d.ts +18 -1
- package/types/ui/agentAttrs.d.ts +14 -0
- package/types/ui/index.d.ts +22 -1
- package/types/ui/overlayLayer.d.ts +13 -0
- package/types/ui/overlayPosition.d.ts +28 -0
- package/types/ui/recipe/badgeRecipe.d.ts +2 -2
- package/types/ui/recipe/buttonRecipe.d.ts +2 -2
- package/types/vendor/use-agentic/AgentAbort.d.ts +17 -0
- package/types/vendor/use-agentic/AgentProgress.d.ts +27 -0
- package/types/vendor/use-agentic/AgentProvider.d.ts +17 -0
- package/types/vendor/use-agentic/AgentScope.d.ts +9 -0
- package/types/vendor/use-agentic/AgentSession.d.ts +163 -0
- package/types/vendor/use-agentic/Agentic.d.ts +21 -0
- package/types/vendor/use-agentic/AgenticSurface.d.ts +58 -0
- package/types/vendor/use-agentic/Compaction.d.ts +48 -0
- package/types/vendor/use-agentic/ToolOutput.d.ts +21 -0
- package/types/vendor/use-agentic/Transcript.d.ts +18 -0
- package/types/vendor/use-agentic/httpRunner.d.ts +15 -0
- package/types/vendor/use-agentic/index.d.ts +19 -0
- package/types/vendor/use-agentic/sharedContext.d.ts +15 -0
- package/types/vendor/use-agentic/surfaceContext.d.ts +5 -0
- package/types/vendor/use-agentic/types.d.ts +182 -0
- package/types/vendor/use-agentic/useAgent.d.ts +4 -0
- package/types/vendor/use-agentic/useAgentGuide.d.ts +6 -0
- package/types/vendor/use-agentic/useAgentResource.d.ts +12 -0
- package/types/vendor/use-agentic/useAgentState.d.ts +16 -0
- package/types/vendor/use-agentic/useAgentTool.d.ts +16 -0
- package/types/vendor/use-agentic.d.ts +1 -0
- package/types/webkit/index.d.ts +4 -0
- package/types/webkit/useBodyScrollLock.d.ts +2 -0
- package/types/webkit/usePageTool.d.ts +19 -0
- package/types/webkit/useScreenScope.d.ts +25 -0
- package/ui/Agent/Approval.tsx +32 -0
- package/ui/Agent/Attach.tsx +77 -0
- package/ui/Agent/Bubble.tsx +192 -0
- package/ui/Agent/Chat.tsx +525 -0
- package/ui/Agent/ChatCommands.ts +141 -0
- package/ui/Agent/Composer.tsx +94 -0
- package/ui/Agent/Context.tsx +49 -0
- package/ui/Agent/Dock.tsx +77 -0
- package/ui/Agent/Guide.tsx +16 -0
- package/ui/Agent/History.tsx +49 -0
- package/ui/Agent/Launcher.tsx +60 -0
- package/ui/Agent/Markdown.tsx +142 -0
- package/ui/Agent/Menu.tsx +55 -0
- package/ui/Agent/Mic.tsx +27 -0
- package/ui/Agent/Question.tsx +63 -0
- package/ui/Agent/Section.tsx +24 -0
- package/ui/Agent/Skip.tsx +30 -0
- package/ui/Agent/StateKey.tsx +46 -0
- package/ui/Agent/Tool.tsx +59 -0
- package/ui/Agent/Transcript.tsx +33 -0
- package/ui/Agent/Zone.tsx +116 -0
- package/ui/Agent/agentSessionOf.ts +60 -0
- package/ui/Agent/attachment.ts +73 -0
- package/ui/Agent/fetchRunner.ts +44 -0
- package/ui/Agent/index.ts +27 -0
- package/ui/Agent/index_.tsx +4 -0
- package/ui/Agent/markdownBlocks.ts +137 -0
- package/ui/Agent/markdownSpans.tsx +49 -0
- package/ui/Agent/markdownTable.ts +54 -0
- package/ui/Agent/sessionHistory.ts +62 -0
- package/ui/Agent/sessionView.ts +38 -0
- package/ui/Agent/tokenCount.ts +10 -0
- package/ui/Agent/useChatAttachments.ts +84 -0
- package/ui/Agent/useChatVoice.ts +129 -0
- package/ui/Agent/useDraftRecall.ts +42 -0
- package/ui/Agent/useKeyboardInset.ts +26 -0
- package/ui/Agent/useSlashMenu.ts +58 -0
- package/ui/Agent/voice.ts +177 -0
- package/ui/Badge.tsx +1 -1
- package/ui/BottomSheet.tsx +32 -36
- package/ui/Button.tsx +3 -1
- package/ui/Clipboard.tsx +3 -6
- package/ui/Constant/Doc.tsx +265 -254
- package/ui/Constant/Graph.tsx +151 -0
- package/ui/Constant/index.ts +3 -2
- package/ui/Constant/schemaGraph.ts +232 -0
- package/ui/Data/CardList.tsx +14 -3
- package/ui/Data/Dashboard.tsx +70 -52
- package/ui/Data/Insight.tsx +18 -12
- package/ui/Data/Item.tsx +42 -56
- package/ui/Data/ListContainer.tsx +246 -132
- package/ui/Data/Pagination.tsx +10 -3
- package/ui/Data/QueryMaker.tsx +160 -11
- package/ui/Data/RefPicker.tsx +202 -0
- package/ui/Data/TableList.tsx +22 -13
- package/ui/Data/dataExport.ts +54 -0
- package/ui/Data/dataText.ts +22 -0
- package/ui/Data/index.ts +13 -1
- package/ui/Data/index_.tsx +1 -0
- package/ui/DatePicker.tsx +110 -128
- package/ui/Dialog/Close.tsx +3 -7
- package/ui/Dialog/LegacyModal.tsx +241 -0
- package/ui/Dialog/Modal.tsx +62 -195
- package/ui/Dialog/Provider.tsx +47 -3
- package/ui/Dialog/Trigger.tsx +3 -7
- package/ui/Dialog/context.ts +14 -2
- package/ui/Dialog/index.tsx +2 -0
- package/ui/DragAction.tsx +3 -2
- package/ui/DraggableList.tsx +9 -4
- package/ui/Dropdown.tsx +89 -27
- package/ui/Empty.tsx +6 -4
- package/ui/Field.tsx +128 -58
- package/ui/Input.tsx +27 -5
- package/ui/KeyboardAvoiding.tsx +2 -2
- package/ui/Layout/BottomTab.tsx +32 -37
- package/ui/Layout/Sider.tsx +37 -14
- package/ui/LegacyModal.tsx +53 -0
- package/ui/Link/CsrLink.tsx +1 -1
- package/ui/Load/Pagination.tsx +15 -8
- package/ui/Load/Units.tsx +30 -7
- package/ui/Load/View.tsx +10 -3
- package/ui/Loading/Area.tsx +7 -6
- package/ui/Loading/Button.tsx +7 -9
- package/ui/Loading/Input.tsx +7 -9
- package/ui/Loading/ProgressBar.tsx +16 -7
- package/ui/Loading/Skeleton.tsx +8 -13
- package/ui/Loading/Spin.tsx +20 -14
- package/ui/Menu.tsx +1 -1
- package/ui/Model/AdminPanel.tsx +52 -12
- package/ui/Model/EditModal.tsx +28 -6
- package/ui/Model/EditWrapper.tsx +16 -4
- package/ui/Model/New.tsx +4 -0
- package/ui/Model/NewWrapper.tsx +2 -0
- package/ui/Model/NewWrapper_Client.tsx +20 -6
- package/ui/Model/Remove.tsx +18 -6
- package/ui/Model/RemoveWrapper.tsx +12 -2
- package/ui/Model/SureToRemove.tsx +18 -6
- package/ui/Model/ViewEditModal.tsx +64 -15
- package/ui/Model/ViewModal.tsx +25 -11
- package/ui/Model/ViewWrapper.tsx +15 -4
- package/ui/Model/index_.tsx +1 -1
- package/ui/Pagination.tsx +51 -66
- package/ui/Popconfirm.tsx +88 -78
- package/ui/Radio.tsx +53 -24
- package/ui/RecentTime.tsx +83 -35
- package/ui/Reference/Collapse.tsx +26 -0
- package/ui/Reference/Panel.tsx +79 -0
- package/ui/Reference/Segmented.tsx +41 -0
- package/ui/Reference/Summary.tsx +25 -0
- package/ui/Reference/Toolbar.tsx +44 -0
- package/ui/Reference/dictText.ts +9 -0
- package/ui/Reference/index.ts +7 -0
- package/ui/Reference/style.ts +45 -0
- package/ui/ScreenNavigator.tsx +17 -2
- package/ui/Select.tsx +96 -57
- package/ui/Signal/Arg.tsx +83 -68
- package/ui/Signal/Doc.tsx +163 -129
- package/ui/Signal/Listener.tsx +40 -29
- package/ui/Signal/Message.tsx +87 -135
- package/ui/Signal/Object.tsx +79 -57
- package/ui/Signal/PubSub.tsx +72 -113
- package/ui/Signal/Request.tsx +2 -22
- package/ui/Signal/Response.tsx +19 -45
- package/ui/Signal/RestApi.tsx +170 -200
- package/ui/Signal/WebSocket.tsx +29 -26
- package/ui/Signal/endpointEntries.ts +59 -0
- package/ui/Signal/makeExample.ts +10 -3
- package/ui/Signal/style.ts +34 -29
- package/ui/Switch.tsx +4 -0
- package/ui/System/CSR.tsx +1 -1
- package/ui/System/Client.tsx +31 -15
- package/ui/System/Common.tsx +3 -4
- package/ui/System/DevModeToggle.tsx +1 -1
- package/ui/System/Gtag.tsx +2 -2
- package/ui/System/Messages.tsx +52 -31
- package/ui/System/Reconnect.tsx +22 -56
- package/ui/System/SelectLanguage.tsx +24 -15
- package/ui/System/ThemeToggle.tsx +25 -13
- package/ui/Tab/Menu.tsx +24 -12
- package/ui/Tab/Menus.tsx +6 -3
- package/ui/Tab/Provider.tsx +30 -3
- package/ui/Tab/context.ts +8 -4
- package/ui/Table.tsx +66 -60
- package/ui/ToggleSelect.tsx +8 -7
- package/ui/Tooltip.tsx +15 -1
- package/ui/UiOverride/context.ts +21 -2
- package/ui/Unauthorized.tsx +6 -4
- package/ui/agentAttrs.ts +19 -0
- package/ui/index.ts +49 -1
- package/ui/overlayLayer.ts +12 -2
- package/ui/overlayPosition.ts +104 -0
- package/ui/recipe/buttonRecipe.ts +2 -2
- package/ui/styles.css +31 -0
- package/vendor/use-agentic/AgentAbort.ts +29 -0
- package/vendor/use-agentic/AgentProgress.ts +40 -0
- package/vendor/use-agentic/AgentProvider.tsx +39 -0
- package/vendor/use-agentic/AgentScope.tsx +20 -0
- package/vendor/use-agentic/AgentSession.ts +750 -0
- package/vendor/use-agentic/Agentic.tsx +44 -0
- package/vendor/use-agentic/AgenticSurface.ts +333 -0
- package/vendor/use-agentic/Compaction.ts +120 -0
- package/vendor/use-agentic/ToolOutput.ts +60 -0
- package/vendor/use-agentic/Transcript.ts +50 -0
- package/vendor/use-agentic/WIRE.md +86 -0
- package/vendor/use-agentic/httpRunner.ts +131 -0
- package/vendor/use-agentic/index.ts +20 -0
- package/vendor/use-agentic/sharedContext.ts +25 -0
- package/vendor/use-agentic/surfaceContext.ts +10 -0
- package/vendor/use-agentic/types.ts +192 -0
- package/vendor/use-agentic/useAgent.ts +18 -0
- package/vendor/use-agentic/useAgentGuide.ts +16 -0
- package/vendor/use-agentic/useAgentResource.ts +36 -0
- package/vendor/use-agentic/useAgentState.ts +64 -0
- package/vendor/use-agentic/useAgentTool.ts +55 -0
- package/webkit/bootCsr.tsx +10 -8
- package/webkit/index.ts +4 -0
- package/webkit/lazy.tsx +5 -1
- package/webkit/useBodyScrollLock.tsx +29 -0
- package/webkit/useFrameRuntime.ts +1 -1
- package/webkit/usePageTool.tsx +37 -0
- package/webkit/useScreenScope.tsx +60 -0
- package/types/ui/Constant/Mermaid.d.ts +0 -8
- package/types/ui/Signal/Collapse.d.ts +0 -12
- package/ui/Constant/Mermaid.tsx +0 -149
- package/ui/Signal/Collapse.tsx +0 -29
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { capitalize } from "./capitalize";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* What MCP says about one endpoint: whether it is published, why it is not, and the hints it carries.
|
|
5
|
+
*
|
|
6
|
+
* Structurally typed like the rest of `common/` so the same rules answer on both sides — the server builds its
|
|
7
|
+
* catalogue from them and the browser API explorer badges an endpoint from them. A second implementation would
|
|
8
|
+
* eventually disagree, and an audit surface that disagrees with the catalogue is worse than none.
|
|
9
|
+
*
|
|
10
|
+
* Every rejection returns the sentence an author reads, at boot in the server log and in the explorer. Fail-closed
|
|
11
|
+
* with no reason leaves an author whose endpoint is missing from the catalogue nowhere to look but the source.
|
|
12
|
+
*/
|
|
13
|
+
export interface McpExposureEndpoint {
|
|
14
|
+
type: string;
|
|
15
|
+
returns: { refName: string };
|
|
16
|
+
args: { name: string; refName: string; type: string; arrDepth?: number; nullable?: boolean }[];
|
|
17
|
+
guards?: string[];
|
|
18
|
+
fileUpload?: boolean;
|
|
19
|
+
mcp?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface McpExposureOption {
|
|
23
|
+
/** The model the endpoint belongs to and the name it is published under: one rule reads the key, not the shape. */
|
|
24
|
+
refName: string;
|
|
25
|
+
key: string;
|
|
26
|
+
/**
|
|
27
|
+
* The read-only deployment valve, which is server configuration. The browser explorer cannot know it and so
|
|
28
|
+
* badges what the code decided; the boot log is where a read-only deployment says what it dropped.
|
|
29
|
+
*/
|
|
30
|
+
readOnly?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** `Any` publishes as the empty schema, which tells a model nothing — so it is left out rather than described. */
|
|
34
|
+
export const isMcpDescribableArg = (arg: { refName: string }) => arg.refName !== "Any";
|
|
35
|
+
|
|
36
|
+
/** Which CRUD verb a generated endpoint key is, or `null` when the key is not one of the five. */
|
|
37
|
+
export const mcpBaseVerbOf = (refName: string, key: string) => {
|
|
38
|
+
const cap = capitalize(refName);
|
|
39
|
+
if (key === refName || key === `light${cap}`) return "get" as const;
|
|
40
|
+
if (key === `create${cap}`) return "create" as const;
|
|
41
|
+
if (key === `update${cap}`) return "update" as const;
|
|
42
|
+
if (key === `remove${cap}`) return "remove" as const;
|
|
43
|
+
return null;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The hints a client renders beside a tool. Hints only — clients are told to distrust them, so they inform a UI
|
|
48
|
+
* and never stand in for a guard. `openWorldHint` is always false: every endpoint reaches this app's own
|
|
49
|
+
* database, not the wider internet.
|
|
50
|
+
*/
|
|
51
|
+
export const mcpHintsOf = (key: string, endpoint: { type: string }) => {
|
|
52
|
+
const readOnly = endpoint.type === "query";
|
|
53
|
+
const destructive = !readOnly && /^(remove|delete)/.test(key);
|
|
54
|
+
return {
|
|
55
|
+
readOnlyHint: readOnly,
|
|
56
|
+
destructiveHint: destructive,
|
|
57
|
+
idempotentHint: readOnly || /^(set|update)/.test(key),
|
|
58
|
+
openWorldHint: false,
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/** The sentence explaining why this endpoint is not in the catalogue, or `null` when it is. */
|
|
63
|
+
export const mcpRefusalOf = (
|
|
64
|
+
endpoint: McpExposureEndpoint,
|
|
65
|
+
{ refName, key, readOnly }: McpExposureOption,
|
|
66
|
+
): string | null => {
|
|
67
|
+
|
|
68
|
+
if (endpoint.mcp === false)
|
|
69
|
+
return "it declares `mcp: false`, so it is deliberately off the agent shelf. HTTP still serves it.";
|
|
70
|
+
|
|
71
|
+
if (!endpoint.guards?.length)
|
|
72
|
+
return "it declares no guards, and exposure follows them — write `guards: [Public]` if anonymous access is the intent.";
|
|
73
|
+
|
|
74
|
+
if (key === `light${capitalize(refName)}`)
|
|
75
|
+
return `it reads the same document as \`${refName}\` in a smaller shape — call \`${refName}\` instead.`;
|
|
76
|
+
if (endpoint.type === "prompt") return mcpPromptRefusalOf(endpoint);
|
|
77
|
+
if (endpoint.type === "pubsub" || endpoint.type === "message")
|
|
78
|
+
return `\`${endpoint.type}\` rides the websocket, and its internal arguments read a socket an MCP request does not have.`;
|
|
79
|
+
if (readOnly && endpoint.type !== "query")
|
|
80
|
+
return "this deployment is read-only, which drops every endpoint that is not a query.";
|
|
81
|
+
if (endpoint.returns.refName === "Any" || endpoint.returns.refName === "Upload")
|
|
82
|
+
return `a return typed \`${endpoint.returns.refName}\` cannot be described to a model.`;
|
|
83
|
+
if (endpoint.returns.refName === "Binary")
|
|
84
|
+
return "a return typed `Binary` is raw bytes, which cost a model its window and tell it nothing.";
|
|
85
|
+
if (endpoint.fileUpload || endpoint.args.some((arg) => arg.refName === "Upload"))
|
|
86
|
+
return "a file upload has no MCP representation.";
|
|
87
|
+
if (endpoint.type === "mutation" && !endpoint.guards.some((name) => name !== "Public"))
|
|
88
|
+
return "a mutation needs a real guard — `[Public]` is having none, spelled out.";
|
|
89
|
+
const opaque = endpoint.args.find((arg) => !isMcpDescribableArg(arg) && arg.type !== "search" && !arg.nullable);
|
|
90
|
+
if (opaque)
|
|
91
|
+
return `its required argument \`${opaque.name}\` is typed \`Any\`, which is left out of the published schema — expose a named filter slice instead.`;
|
|
92
|
+
return null;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* A prompt is a read exposed on the same terms as a query, so every rejection here is one thing: an argument
|
|
97
|
+
* `prompts/get` cannot carry. Its `arguments` is a flat string map — one string per name, and no schema beside it
|
|
98
|
+
* — which rules out the argument *kinds* the builder already refuses and, just as surely, two argument *types* it
|
|
99
|
+
* accepts. A tool escapes both because it publishes a real JSON Schema.
|
|
100
|
+
*/
|
|
101
|
+
export const mcpPromptRefusalOf = (endpoint: McpExposureEndpoint): string | null => {
|
|
102
|
+
const carried = endpoint.args.find((arg) => arg.type === "body" || arg.type === "msg" || arg.type === "room");
|
|
103
|
+
if (carried)
|
|
104
|
+
return `a prompt's arguments travel as a flat string map, so its \`${carried.type}\` argument \`${carried.name}\` cannot be carried.`;
|
|
105
|
+
|
|
106
|
+
const list = endpoint.args.find((arg) => arg.arrDepth);
|
|
107
|
+
if (list)
|
|
108
|
+
return `a prompt argument is one string, so its list argument \`${list.name}\` could never carry more than one value.`;
|
|
109
|
+
|
|
110
|
+
const opaque = endpoint.args.find((arg) => !isMcpDescribableArg(arg));
|
|
111
|
+
if (opaque)
|
|
112
|
+
return `its argument \`${opaque.name}\` is typed \`Any\`, and a prompt has no schema in which to describe one.`;
|
|
113
|
+
return null;
|
|
114
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
type Indexable = Record<string, unknown>;
|
|
2
|
+
|
|
3
|
+
const isIndexable = (value: unknown): value is Indexable => Object(value) === value;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Reads a dotted path whose segments may themselves contain the separator.
|
|
7
|
+
*
|
|
8
|
+
* Dictionary keys are built as `<refName>.<value>` and an enum value is a real-world identifier — `gpt-5.6-terra`,
|
|
9
|
+
* `v1.2` — so the key is not a clean dotted path and `pathGet` splits it into segments that were never nodes.
|
|
10
|
+
* The tree stores such a key literally, so resolution has to try joined prefixes too.
|
|
11
|
+
*/
|
|
12
|
+
export const pathGetLoose = (
|
|
13
|
+
path: string | readonly string[],
|
|
14
|
+
obj: unknown,
|
|
15
|
+
separator = ".",
|
|
16
|
+
fallback: unknown = null,
|
|
17
|
+
): unknown => {
|
|
18
|
+
const walk = (node: unknown, rest: readonly string[]): unknown => {
|
|
19
|
+
if (!rest.length) return node;
|
|
20
|
+
if (!isIndexable(node)) return undefined;
|
|
21
|
+
|
|
22
|
+
for (let take = 1; take <= rest.length; take += 1) {
|
|
23
|
+
const child = node[rest.slice(0, take).join(separator)];
|
|
24
|
+
if (child === undefined) continue;
|
|
25
|
+
const found = walk(child, rest.slice(take));
|
|
26
|
+
if (found !== undefined) return found;
|
|
27
|
+
}
|
|
28
|
+
return undefined;
|
|
29
|
+
};
|
|
30
|
+
return walk(obj, Array.isArray(path) ? [...path] : (path as string).split(separator)) ?? fallback;
|
|
31
|
+
};
|
package/common/pathSet.ts
CHANGED
|
@@ -1,16 +1,28 @@
|
|
|
1
1
|
type MutableIndexable = Record<string | number, unknown>;
|
|
2
2
|
type PathSegment = string | number;
|
|
3
|
+
type Container = MutableIndexable | Map<PathSegment, unknown>;
|
|
3
4
|
|
|
4
5
|
const toPathSegments = (path: string | readonly PathSegment[]) =>
|
|
5
6
|
Array.isArray(path) ? [...path] : path.toString().match(/[^.[\]]+/g) || [];
|
|
6
7
|
|
|
8
|
+
const readChild = (container: Container, key: PathSegment) =>
|
|
9
|
+
container instanceof Map ? container.get(key) : container[key];
|
|
10
|
+
|
|
11
|
+
const writeChild = (container: Container, key: PathSegment, value: unknown) => {
|
|
12
|
+
if (container instanceof Map) container.set(key, value);
|
|
13
|
+
else container[key] = value;
|
|
14
|
+
};
|
|
15
|
+
|
|
7
16
|
export const pathSet = <T>(obj: T, path: string | readonly PathSegment[], value: unknown): T => {
|
|
8
17
|
if (Object(obj) !== obj) return obj;
|
|
9
18
|
const pathSegments = toPathSegments(path);
|
|
10
|
-
pathSegments.slice(0, -1).reduce<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
19
|
+
const parent = pathSegments.slice(0, -1).reduce<Container>((a, c, i) => {
|
|
20
|
+
const child = readChild(a, c);
|
|
21
|
+
if (Object(child) === child) return child as Container;
|
|
22
|
+
const created = Math.abs(Number(pathSegments[i + 1])) >> 0 === +pathSegments[i + 1] ? [] : {};
|
|
23
|
+
writeChild(a, c, created);
|
|
24
|
+
return created as unknown as Container;
|
|
25
|
+
}, obj as Container);
|
|
26
|
+
writeChild(parent, pathSegments[pathSegments.length - 1], value);
|
|
15
27
|
return obj;
|
|
16
28
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Own and inherited enumerable data of an object as a plain record. An Akan model keeps its Date fields as
|
|
3
|
+
* enumerable prototype accessors, which `Object.keys` and a spread never reach; methods are non-enumerable and stay
|
|
4
|
+
* out either way.
|
|
5
|
+
*/
|
|
6
|
+
export const plainFieldsOf = (source: object): Record<string, unknown> => {
|
|
7
|
+
const out: Record<string, unknown> = {};
|
|
8
|
+
for (const key in source) {
|
|
9
|
+
const value = (source as Record<string, unknown>)[key];
|
|
10
|
+
if (typeof value !== "function") out[key] = value;
|
|
11
|
+
}
|
|
12
|
+
return out;
|
|
13
|
+
};
|
|
@@ -67,27 +67,37 @@ export function isRouteSourceFile(filePath: string): boolean {
|
|
|
67
67
|
return tryParseRouteModuleKey(key) !== null;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Why a `page/` file breaks the route convention, or null when it is fine. Null also covers a non-source
|
|
72
|
+
* asset, which `page/` tolerates. `akan sync <lib>` reports these alongside its other layout violations,
|
|
73
|
+
* so the rule stays in one place instead of being restated where it cannot afford to throw.
|
|
74
|
+
*/
|
|
75
|
+
export function getPageSourceFileViolation(filePath: string): string | null {
|
|
76
|
+
if (!SOURCE_EXT_RE.test(filePath)) return null;
|
|
72
77
|
|
|
73
78
|
const key = filePath.startsWith("./") ? filePath : `./${filePath.split(/[\\/]/).join("/")}`;
|
|
74
79
|
const match = ROUTE_SOURCE_RE.exec(key);
|
|
75
|
-
|
|
76
|
-
if (!match) throw new Error(`[route-convention] invalid page source file: ${displayPath}`);
|
|
80
|
+
if (!match) return "invalid page source file";
|
|
77
81
|
|
|
78
82
|
const file = match[1] as string;
|
|
79
83
|
const ext = match[2] as string;
|
|
80
84
|
const leaf = file.split("/").filter(Boolean).at(-1);
|
|
81
|
-
if (!leaf)
|
|
85
|
+
if (!leaf) return "invalid page source file";
|
|
82
86
|
|
|
83
|
-
if (ext !== "tsx")
|
|
87
|
+
if (ext !== "tsx") return "route source files under page/ must use .tsx";
|
|
84
88
|
if (leaf.startsWith("_") && !RESERVED_ROUTE_FILES.has(leaf) && leaf !== INTERNAL_ROOT_LAYOUT_LEAF)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
return "only _index.tsx, _layout.tsx and _overrides.tsx are allowed as reserved route files under page/";
|
|
90
|
+
if (/^[A-Z]/.test(leaf)) return "route page filenames must not start with an uppercase letter";
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function validatePageSourceFile(filePath: string, options: ValidatePageSourceFileOptions = {}): boolean {
|
|
95
|
+
if (!SOURCE_EXT_RE.test(filePath)) return false;
|
|
96
|
+
|
|
97
|
+
const violation = getPageSourceFileViolation(filePath);
|
|
98
|
+
if (!violation) return true;
|
|
99
|
+
const key = filePath.startsWith("./") ? filePath : `./${filePath.split(/[\\/]/).join("/")}`;
|
|
100
|
+
throw new Error(`[route-convention] ${violation}: ${options.filePath ?? key}`);
|
|
91
101
|
}
|
|
92
102
|
|
|
93
103
|
export function validateSubRoutePageKey(
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface WebsocketBinaryFrame {
|
|
2
|
+
roomId: string;
|
|
3
|
+
payload: Uint8Array;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const MAGIC = 0xab;
|
|
7
|
+
const KIND_PUB = 0x01;
|
|
8
|
+
const HEADER_BYTES = 4;
|
|
9
|
+
const MAX_ROOM_BYTES = 0xffff;
|
|
10
|
+
|
|
11
|
+
const encoder = new TextEncoder();
|
|
12
|
+
const decoder = new TextDecoder();
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Framework-owned binary pubsub frame, shared by the publisher and the client dispatcher. A room whose whole
|
|
16
|
+
* return is `Binary` sends its bytes in a websocket binary frame instead of the JSON `{ type: "pub" }` envelope,
|
|
17
|
+
* because `Buffer.toJSON()` turns bytes into `{ type: "Buffer", data: number[] }` — 3.6x the wire and ~300x the
|
|
18
|
+
* encode cost on a 64 KB payload, and a shape `JSON.parse` never restores.
|
|
19
|
+
*
|
|
20
|
+
* Text and binary frames coexist on one socket, so this is additive: every JSON endpoint is untouched, and a
|
|
21
|
+
* federation gateway relays a binary frame unchanged with no code of its own.
|
|
22
|
+
*/
|
|
23
|
+
export const websocketBinaryFrameContract = {
|
|
24
|
+
encode: ({ roomId, payload }: WebsocketBinaryFrame): Uint8Array => {
|
|
25
|
+
const room = encoder.encode(roomId);
|
|
26
|
+
if (room.length > MAX_ROOM_BYTES) throw new Error(`Room id is too long to frame: ${roomId}`);
|
|
27
|
+
const frame = new Uint8Array(HEADER_BYTES + room.length + payload.length);
|
|
28
|
+
frame[0] = MAGIC;
|
|
29
|
+
frame[1] = KIND_PUB;
|
|
30
|
+
frame[2] = room.length >> 8;
|
|
31
|
+
frame[3] = room.length & 0xff;
|
|
32
|
+
frame.set(room, HEADER_BYTES);
|
|
33
|
+
frame.set(payload, HEADER_BYTES + room.length);
|
|
34
|
+
return frame;
|
|
35
|
+
},
|
|
36
|
+
decode: (data: ArrayBuffer | Uint8Array): WebsocketBinaryFrame | null => {
|
|
37
|
+
const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
38
|
+
if (bytes.length < HEADER_BYTES || bytes[0] !== MAGIC || bytes[1] !== KIND_PUB) return null;
|
|
39
|
+
const roomBytes = (bytes[2] << 8) | bytes[3];
|
|
40
|
+
if (bytes.length < HEADER_BYTES + roomBytes) return null;
|
|
41
|
+
return {
|
|
42
|
+
roomId: decoder.decode(bytes.subarray(HEADER_BYTES, HEADER_BYTES + roomBytes)),
|
|
43
|
+
payload: bytes.subarray(HEADER_BYTES + roomBytes),
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
} as const;
|
package/constant/crystalize.ts
CHANGED
|
@@ -8,38 +8,104 @@ import {
|
|
|
8
8
|
} from "akanjs/base";
|
|
9
9
|
|
|
10
10
|
import type { FieldProps } from ".";
|
|
11
|
+
import { ConstantRegistry } from "./constantRegistry";
|
|
11
12
|
|
|
12
13
|
export type CrystalizeFunc<Model> = (self: GetStateObject<Model>, isChild?: boolean) => Model;
|
|
14
|
+
export type Converter = (value: unknown) => unknown;
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
16
|
+
/**
|
|
17
|
+
* The relation instances one hydration pass has already built, by model class and then document id.
|
|
18
|
+
*
|
|
19
|
+
* A listing hands the same relation to every row that references it — twenty users wearing one avatar — and
|
|
20
|
+
* each row would otherwise build its own copy of it, re-parsing every `Date` on the way. Sharing is safe
|
|
21
|
+
* because a constant model is `[immerable]`: a store write copies before it mutates.
|
|
22
|
+
*
|
|
23
|
+
* Module-scoped rather than passed down, because `crystalize` is reached through a model's own constructor,
|
|
24
|
+
* which has nowhere to carry it. A pass is wholly synchronous, so no other one can observe this mid-flight.
|
|
25
|
+
*/
|
|
26
|
+
let sharedInstances: Map<Cls, Map<string, object>> | null = null;
|
|
27
|
+
|
|
28
|
+
/** Runs one hydration pass, sharing a relation instance across every value in it that names the same id. */
|
|
29
|
+
export const withSharedInstances = <T>(hydrate: () => T): T => {
|
|
30
|
+
if (sharedInstances) return hydrate();
|
|
31
|
+
sharedInstances = new Map();
|
|
32
|
+
try {
|
|
33
|
+
return hydrate();
|
|
34
|
+
} finally {
|
|
35
|
+
sharedInstances = null;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
type ModelCls = new (obj?: object) => object;
|
|
40
|
+
|
|
41
|
+
const relationIdOf = (value: object): string | null => {
|
|
42
|
+
const id = (value as { id?: unknown }).id;
|
|
43
|
+
return typeof id === "string" && id ? id : null;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const modelConverterOf = (props: FieldProps): Converter => {
|
|
47
|
+
const modelRef = props.modelRef as unknown as ModelCls;
|
|
48
|
+
|
|
49
|
+
if (props.isScalar) return (value) => (value instanceof modelRef ? value : new modelRef(value as object));
|
|
50
|
+
return (value) => {
|
|
51
|
+
if (value instanceof modelRef) return value;
|
|
52
|
+
|
|
53
|
+
const id = relationIdOf(value as object);
|
|
54
|
+
if (!sharedInstances || !id) return new modelRef(value as object);
|
|
55
|
+
const byId = sharedInstances.get(modelRef as unknown as Cls) ?? new Map<string, object>();
|
|
56
|
+
if (!sharedInstances.has(modelRef as unknown as Cls)) sharedInstances.set(modelRef as unknown as Cls, byId);
|
|
57
|
+
const shared = byId.get(id) ?? new modelRef(value as object);
|
|
58
|
+
byId.set(id, shared);
|
|
59
|
+
return shared;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const mapConverterOf = (props: FieldProps): Converter => {
|
|
64
|
+
const of = props.of as Cls | undefined;
|
|
65
|
+
const valueConverter: Converter = of
|
|
66
|
+
? singleConverterOf({
|
|
67
|
+
...props,
|
|
68
|
+
modelRef: of as FieldProps["modelRef"],
|
|
69
|
+
isMap: false,
|
|
70
|
+
isClass: !PrimitiveRegistry.has(of),
|
|
71
|
+
isScalar: PrimitiveRegistry.has(of) || ConstantRegistry.isScalar(of),
|
|
72
|
+
isArray: false,
|
|
73
|
+
arrDepth: 0,
|
|
74
|
+
})
|
|
75
|
+
: (value) => value;
|
|
76
|
+
return (value) => {
|
|
77
|
+
|
|
78
|
+
const entries = value instanceof Map ? [...value.entries()] : Object.entries(value as Record<string, unknown>);
|
|
33
79
|
return new Map(
|
|
34
|
-
|
|
35
|
-
key,
|
|
36
|
-
field.of
|
|
37
|
-
? applyFnToArrayObjects(val, (v: never) => crystalize(mapValueField, v))
|
|
38
|
-
: applyFnToArrayObjects(val, crystalizeValue),
|
|
39
|
-
]),
|
|
80
|
+
entries.map(([key, val]: [string, unknown]) => [key, applyFnToArrayObjects(val, valueConverter as never)]),
|
|
40
81
|
);
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const singleConverterOf = (props: FieldProps): Converter => {
|
|
86
|
+
if (props.isMap) return mapConverterOf(props);
|
|
87
|
+
if (props.isClass) return modelConverterOf(props);
|
|
88
|
+
|
|
89
|
+
if ((props.modelRef as unknown) === Date) return (value) => dayjs(value as Date);
|
|
90
|
+
if (PrimitiveRegistry.has(props.modelRef as Cls))
|
|
91
|
+
return (value) => (props.modelRef as unknown as typeof PrimitiveScalar)._parse(value as never);
|
|
92
|
+
return (value) => value;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const converters = new WeakMap<FieldProps, Converter>();
|
|
96
|
+
|
|
97
|
+
/** The converter for one field, compiled once per `FieldProps` — which `getProps()` freezes and shares per field. */
|
|
98
|
+
export const converterOf = (props: FieldProps): Converter => {
|
|
99
|
+
const cached = converters.get(props);
|
|
100
|
+
if (cached) return cached;
|
|
101
|
+
const single = singleConverterOf(props);
|
|
102
|
+
let convert: Converter = (value) => (value === null || value === undefined ? value : single(value));
|
|
103
|
+
for (let depth = props.arrDepth; depth > 0; depth--) {
|
|
104
|
+
const inner: Converter = convert;
|
|
105
|
+
convert = (value: unknown): unknown => (Array.isArray(value) ? value.map(inner) : inner(value));
|
|
41
106
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return crystalizeValue(value);
|
|
107
|
+
converters.set(props, convert);
|
|
108
|
+
return convert;
|
|
45
109
|
};
|
|
110
|
+
|
|
111
|
+
export const crystalize = (field: FieldProps, value: unknown): unknown => converterOf(field)(value);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type Dayjs, dayjs } from "akanjs/base";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A Date field stores a native `Date` under a per-key symbol and builds the `Dayjs` its type promises on first
|
|
5
|
+
* read, memoized by that `Date`. A dayjs instance is ~300 bytes and eight getter calls at construction; a `Date`
|
|
6
|
+
* is 40 bytes. A listing carries every row's dates and reads a handful of them, so this is most of what a
|
|
7
|
+
* hydrated list used to cost — see `crystalize`.
|
|
8
|
+
*
|
|
9
|
+
* The slot is a function of the key, not the class (`Symbol.for`): `applyMixins` copies a light model's accessors
|
|
10
|
+
* onto the full model's prototype, so an accessor and the `set()` that fills its slot must agree on the slot
|
|
11
|
+
* whichever class defined either one.
|
|
12
|
+
*/
|
|
13
|
+
const slotByKey = new Map<string, symbol>();
|
|
14
|
+
export const dateSlotOf = (key: string): symbol => {
|
|
15
|
+
const cached = slotByKey.get(key);
|
|
16
|
+
if (cached) return cached;
|
|
17
|
+
const slot = Symbol.for(`akan.date.${key}`);
|
|
18
|
+
slotByKey.set(key, slot);
|
|
19
|
+
return slot;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const dayjsByDate = new WeakMap<Date, Dayjs>();
|
|
23
|
+
const lazyDayjsOf = (date: Date): Dayjs => {
|
|
24
|
+
const cached = dayjsByDate.get(date);
|
|
25
|
+
if (cached) return cached;
|
|
26
|
+
const value = dayjs(date);
|
|
27
|
+
dayjsByDate.set(date, value);
|
|
28
|
+
return value;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/** A caller's own `Date` is copied: the slot must not alias an object the caller can still mutate. */
|
|
32
|
+
export const toDateValue = (value: unknown): Date | null | undefined => {
|
|
33
|
+
if (value === null || value === undefined) return value;
|
|
34
|
+
if (value instanceof Date) return new Date(value.getTime());
|
|
35
|
+
if (dayjs.isDayjs(value)) return value.toDate();
|
|
36
|
+
return new Date(value as string | number);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
type DateSlotHolder = Record<symbol, Date | null | undefined>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Enumerable so `for...in` — `plainFieldsOf`, `immerify`, `deepObjectify` — still sees the field. immer calls a
|
|
43
|
+
* prototype setter with the draft as `this`, so a write through the accessor stays copy-on-write, and the getter
|
|
44
|
+
* writes nothing, so a read never marks a draft modified.
|
|
45
|
+
*/
|
|
46
|
+
export const dateAccessorOf = (key: string): PropertyDescriptor => {
|
|
47
|
+
const slot = dateSlotOf(key);
|
|
48
|
+
return {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
configurable: true,
|
|
51
|
+
get(this: DateSlotHolder) {
|
|
52
|
+
const date = this[slot];
|
|
53
|
+
return date === null || date === undefined ? date : lazyDayjsOf(date);
|
|
54
|
+
},
|
|
55
|
+
set(this: DateSlotHolder, value: unknown) {
|
|
56
|
+
this[slot] = toDateValue(value);
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const isDateSlotField = (props: { modelRef: unknown; isArray: boolean; isMap: boolean }): boolean =>
|
|
62
|
+
props.modelRef === Date && !props.isArray && !props.isMap;
|
package/constant/deserialize.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Any, applyFnToArrayObjects, type Cls, FIELD_META, PrimitiveRegistry, type PrimitiveScalar } from "akanjs/base";
|
|
2
2
|
|
|
3
|
-
import { type ConstantCls, type ConstantModelRef, ConstantRegistry, type FieldProps } from ".";
|
|
3
|
+
import { type ConstantCls, type ConstantModelRef, ConstantRegistry, type FieldProps, withSharedInstances } from ".";
|
|
4
4
|
|
|
5
5
|
const getDeserializeFn = (inputRef: ConstantModelRef | PrimitiveScalar) => {
|
|
6
6
|
const deserializeFn = PrimitiveRegistry.has(inputRef as Cls)
|
|
@@ -66,5 +66,6 @@ export const deserialize = (
|
|
|
66
66
|
if (nullable && (value === null || value === undefined)) return null;
|
|
67
67
|
else if (!nullable && (value === null || value === undefined) && argRef !== Any)
|
|
68
68
|
throw new Error(`Invalid Value (Nullable) in ${key} ${argRef} for value ${value}`);
|
|
69
|
-
|
|
69
|
+
|
|
70
|
+
return withSharedInstances(() => deserializeInput(value, argRef, arrDepth, convertFn)) as object[];
|
|
70
71
|
};
|
package/constant/fieldInfo.ts
CHANGED
|
@@ -106,6 +106,13 @@ export interface ConstantFieldProps<
|
|
|
106
106
|
validate?: (value: FieldValue, model: any) => boolean;
|
|
107
107
|
text?: TextFieldRole;
|
|
108
108
|
cascade?: CascadeAction;
|
|
109
|
+
/**
|
|
110
|
+
* Renders on the page, never reaches an agent. Stripped wherever a value is masked for an AI caller — the
|
|
111
|
+
* in-page agent's reads and every MCP result — and left untouched everywhere else, so a `File`'s blur
|
|
112
|
+
* placeholder still ships to `<Image>`. Unlike `hidden`/`secret` this is about cost, not secrecy: a field
|
|
113
|
+
* nothing can answer a question with is pure spend on every turn it rides.
|
|
114
|
+
*/
|
|
115
|
+
visual?: boolean;
|
|
109
116
|
meta?: Metadata;
|
|
110
117
|
}
|
|
111
118
|
export const fieldPresets = ["email", "password", "url"] as const;
|
|
@@ -197,6 +204,7 @@ interface ConstantFieldBuildProps<
|
|
|
197
204
|
validate?: (value: FieldValue, model: any) => boolean;
|
|
198
205
|
text?: TextFieldRole;
|
|
199
206
|
cascade?: CascadeAction;
|
|
207
|
+
visual: boolean;
|
|
200
208
|
modelRef: ConstantModelRef;
|
|
201
209
|
arrDepth: number;
|
|
202
210
|
optArrDepth: number;
|
|
@@ -321,6 +329,7 @@ export class ConstantField<
|
|
|
321
329
|
readonly validate?: (value: FieldValue, model: any) => boolean;
|
|
322
330
|
readonly text?: TextFieldRole;
|
|
323
331
|
readonly cascade?: CascadeAction;
|
|
332
|
+
readonly visual: boolean;
|
|
324
333
|
readonly modelRef: ConstantModelRef;
|
|
325
334
|
readonly arrDepth: number;
|
|
326
335
|
readonly optArrDepth: number;
|
|
@@ -353,6 +362,7 @@ export class ConstantField<
|
|
|
353
362
|
this.validate = props.validate;
|
|
354
363
|
this.text = props.text;
|
|
355
364
|
this.cascade = props.cascade;
|
|
365
|
+
this.visual = props.visual;
|
|
356
366
|
this.modelRef = props.modelRef;
|
|
357
367
|
this.arrDepth = props.arrDepth;
|
|
358
368
|
this.optArrDepth = props.optArrDepth;
|
|
@@ -432,6 +442,7 @@ export class ConstantField<
|
|
|
432
442
|
validate: option.validate,
|
|
433
443
|
text: option.text,
|
|
434
444
|
cascade: option.cascade,
|
|
445
|
+
visual: option.visual ?? false,
|
|
435
446
|
modelRef,
|
|
436
447
|
arrDepth: arrDepth,
|
|
437
448
|
optArrDepth: optArrDepth,
|
|
@@ -478,6 +489,7 @@ export class ConstantField<
|
|
|
478
489
|
validate: this.validate,
|
|
479
490
|
text: this.text,
|
|
480
491
|
cascade: this.cascade,
|
|
492
|
+
visual: this.visual,
|
|
481
493
|
modelRef: this.modelRef,
|
|
482
494
|
arrDepth: this.arrDepth,
|
|
483
495
|
optArrDepth: this.optArrDepth,
|
|
@@ -493,6 +505,14 @@ export interface FieldObject {
|
|
|
493
505
|
[key: string]: ConstantField;
|
|
494
506
|
}
|
|
495
507
|
|
|
508
|
+
/**
|
|
509
|
+
* `text` names a column in the plaintext search mirror, so a masked field carrying one would publish what it
|
|
510
|
+
* masks through search — the class build refuses it (`TextFieldPaths`). Removing the key from the option type
|
|
511
|
+
* moves that refusal to the call site, where the fix is obvious. Distributive because `FieldOption` is a union:
|
|
512
|
+
* a plain `Omit` over it would collapse to the keys the members share.
|
|
513
|
+
*/
|
|
514
|
+
type WithoutTextRole<Option> = Option extends unknown ? Omit<Option, "text"> : never;
|
|
515
|
+
|
|
496
516
|
type FieldOption<
|
|
497
517
|
Value extends ConstantFieldTypeInput,
|
|
498
518
|
MapValue = Value extends MapConstructor ? typeof PrimitiveScalar : never,
|
|
@@ -530,13 +550,33 @@ export const field = <
|
|
|
530
550
|
fieldType: "property",
|
|
531
551
|
});
|
|
532
552
|
|
|
533
|
-
|
|
553
|
+
/**
|
|
554
|
+
* A stored property the page renders and an agent never sees — `field(value, { visual: true })`, spelled short
|
|
555
|
+
* because the reason to reach for it is always the same one. A blur placeholder, a rendered HTML body, a
|
|
556
|
+
* serialized geometry: real data the screen needs, and hundreds of tokens per record that no question is answered
|
|
557
|
+
* from. It stays a plain `property` everywhere else, so persistence, search, forms and the page response are
|
|
558
|
+
* untouched.
|
|
559
|
+
*/
|
|
560
|
+
field.visual = <
|
|
534
561
|
ExplicitType,
|
|
535
562
|
Value extends ConstantFieldTypeInput = PlainTypeToFieldType<ExplicitType>,
|
|
536
563
|
MapValue = Value extends MapConstructor ? typeof PrimitiveScalar : never,
|
|
537
564
|
>(
|
|
538
565
|
value: Value,
|
|
539
566
|
option: FieldOption<Value, MapValue> = {},
|
|
567
|
+
) =>
|
|
568
|
+
new FieldInfo<"property", Value, ExplicitType, MapValue>(value, {
|
|
569
|
+
...option,
|
|
570
|
+
fieldType: "property",
|
|
571
|
+
visual: true,
|
|
572
|
+
});
|
|
573
|
+
field.hidden = <
|
|
574
|
+
ExplicitType,
|
|
575
|
+
Value extends ConstantFieldTypeInput = PlainTypeToFieldType<ExplicitType>,
|
|
576
|
+
MapValue = Value extends MapConstructor ? typeof PrimitiveScalar : never,
|
|
577
|
+
>(
|
|
578
|
+
value: Value,
|
|
579
|
+
option: WithoutTextRole<FieldOption<Value, MapValue>> = {},
|
|
540
580
|
) =>
|
|
541
581
|
new FieldInfo<"hidden", Value, ExplicitType, MapValue>(value, {
|
|
542
582
|
...option,
|
|
@@ -549,7 +589,7 @@ field.secret = <
|
|
|
549
589
|
MapValue = Value extends MapConstructor ? typeof PrimitiveScalar : never,
|
|
550
590
|
>(
|
|
551
591
|
value: Value,
|
|
552
|
-
option: FieldOption<Value, MapValue
|
|
592
|
+
option: WithoutTextRole<FieldOption<Value, MapValue>> = {},
|
|
553
593
|
) =>
|
|
554
594
|
new FieldInfo<"secret", Value | null, ExplicitType | null, MapValue>(value, {
|
|
555
595
|
...option,
|
|
@@ -564,7 +604,7 @@ export const resolve = <
|
|
|
564
604
|
MapValue = Value extends MapConstructor ? typeof PrimitiveScalar : never,
|
|
565
605
|
>(
|
|
566
606
|
value: Value,
|
|
567
|
-
option: FieldOption<Value, MapValue
|
|
607
|
+
option: WithoutTextRole<FieldOption<Value, MapValue>> = {},
|
|
568
608
|
) =>
|
|
569
609
|
new FieldInfo<"resolve", Value, ExplicitType, MapValue>(value, {
|
|
570
610
|
...option,
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { FIELD_META } from "akanjs/base";
|
|
2
|
+
import { ConstantRegistry } from "./constantRegistry";
|
|
3
|
+
import type { FieldObject } from "./fieldInfo";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The query a field's value stands for, declared on the field itself with `.meta(...)`. A summary counter is the
|
|
7
|
+
* case this exists for: `hau` is however many rows one filter returns, so the tile showing it can open that exact
|
|
8
|
+
* listing without the page restating the filter beside it.
|
|
9
|
+
*
|
|
10
|
+
* The shape is read structurally rather than by class, so an app declares it with whatever builder it already has.
|
|
11
|
+
*/
|
|
12
|
+
export interface FieldQueryMeta {
|
|
13
|
+
/** The model the query runs against. */
|
|
14
|
+
refName: string;
|
|
15
|
+
/** One of that model's declared filter keys. */
|
|
16
|
+
queryKey: string | null;
|
|
17
|
+
/** Read when the query is applied, so an arg relative to now — `() => [dayjs().subtract(1, "hour")]` — is current. */
|
|
18
|
+
queryArgs?: unknown[] | (() => unknown[]);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const isFieldQueryMeta = (meta: unknown): meta is FieldQueryMeta => {
|
|
22
|
+
if (!meta || typeof meta !== "object") return false;
|
|
23
|
+
const { refName, queryKey, queryArgs } = meta as Record<string, unknown>;
|
|
24
|
+
if (typeof refName !== "string" || !refName) return false;
|
|
25
|
+
if (queryKey !== null && typeof queryKey !== "string") return false;
|
|
26
|
+
return queryArgs === undefined || Array.isArray(queryArgs) || typeof queryArgs === "function";
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/** The query one field of `refName` names, or nothing when the model, the field, or the declaration is absent. */
|
|
30
|
+
export const fieldQueryMetaOf = (refName: string, field: string): FieldQueryMeta | undefined => {
|
|
31
|
+
const cnst = ConstantRegistry.getDatabase(refName, { allowEmpty: true });
|
|
32
|
+
const fieldMap = cnst?.full[FIELD_META] as FieldObject | undefined;
|
|
33
|
+
const meta = fieldMap?.[field]?.meta;
|
|
34
|
+
return isFieldQueryMeta(meta) ? meta : undefined;
|
|
35
|
+
};
|