@infinityi/engine-lib 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -445
- package/dist/agent/index.js +14 -8
- package/dist/context/index.d.ts +1 -1
- package/dist/context/index.js +8 -5
- package/dist/context/providers.d.ts +3 -3
- package/dist/context/types.d.ts +16 -1
- package/dist/errors.d.ts +18 -0
- package/dist/errors.js +6 -1
- package/dist/events/index.js +2 -1
- package/dist/execution/index.js +9 -4
- package/dist/execution/types.d.ts +14 -0
- package/dist/index-37x76zdn.js +4 -0
- package/dist/index-4c15ysa8.js +84 -0
- package/dist/{index-pwr8179t.js → index-7nb9qwa1.js} +23 -14
- package/dist/{index-jxgj4z08.js → index-9egrqxkf.js} +4 -0
- package/dist/index-9rr5dkzh.js +0 -0
- package/dist/{index-w34cbktd.js → index-a67ej96j.js} +1 -0
- package/dist/{index-64tt9696.js → index-aed6fe4z.js} +3 -3
- package/dist/{index-7690reng.js → index-ajr3nk10.js} +15 -1
- package/dist/index-c6kgts41.js +0 -0
- package/dist/{index-xsv43c5j.js → index-e14g2e48.js} +2 -2
- package/dist/index-k0q7x4mz.js +54 -0
- package/dist/index-mnx5mqbs.js +102 -0
- package/dist/index-mr1hs98z.js +661 -0
- package/dist/{index-yrqrxwjt.js → index-nvdsr51v.js} +4 -38
- package/dist/{index-jp2b31xs.js → index-vwcyawfk.js} +4 -4
- package/dist/index-ycjsqfpq.js +39 -0
- package/dist/{index-bqg01r42.js → index-zdggff0y.js} +183 -180
- package/dist/index.d.ts +2 -2
- package/dist/index.js +49 -38
- package/dist/lifecycle/index.js +2 -0
- package/dist/messages/index.js +1 -0
- package/dist/providers/index.js +5 -4
- package/dist/retrieval/chunking.d.ts +8 -0
- package/dist/retrieval/context.d.ts +4 -0
- package/dist/retrieval/index.d.ts +19 -0
- package/dist/retrieval/index.js +747 -0
- package/dist/retrieval/loaders.d.ts +8 -0
- package/dist/retrieval/memory.d.ts +29 -0
- package/dist/retrieval/retriever.d.ts +8 -0
- package/dist/retrieval/types.d.ts +253 -0
- package/dist/retrieval/utils.d.ts +11 -0
- package/dist/retrieval/vector-store.d.ts +13 -0
- package/dist/runtime/index.js +2 -1
- package/dist/schema/index.js +10 -4
- package/dist/session/index.js +1 -0
- package/dist/session-stores/codec.d.ts +8 -0
- package/dist/session-stores/forge-data.d.ts +43 -0
- package/dist/session-stores/hooks.d.ts +4 -0
- package/dist/session-stores/ids.d.ts +3 -0
- package/dist/session-stores/index.d.ts +20 -0
- package/dist/session-stores/index.js +1382 -0
- package/dist/session-stores/jsonl.d.ts +26 -0
- package/dist/session-stores/redis.d.ts +45 -0
- package/dist/session-stores/types.d.ts +45 -0
- package/dist/session-stores/versioning.d.ts +6 -0
- package/dist/testing/conformance.js +5 -4
- package/dist/testing/index.js +1 -0
- package/dist/tools/index.js +5 -3
- package/dist/tools-fs/define.d.ts +2 -0
- package/dist/tools-fs/files.d.ts +40 -0
- package/dist/tools-fs/git.d.ts +14 -0
- package/dist/tools-fs/index.d.ts +19 -0
- package/dist/tools-fs/index.js +1695 -0
- package/dist/tools-fs/policy.d.ts +32 -0
- package/dist/tools-fs/schemas.d.ts +31 -0
- package/dist/tools-fs/search.d.ts +45 -0
- package/dist/tools-fs/symbols.d.ts +12 -0
- package/dist/tools-fs/types.d.ts +151 -0
- package/dist/tools-http/client.d.ts +12 -0
- package/dist/tools-http/define.d.ts +12 -0
- package/dist/tools-http/events.d.ts +22 -0
- package/dist/tools-http/index.d.ts +24 -0
- package/dist/tools-http/index.js +18 -0
- package/dist/tools-http/policy.d.ts +52 -0
- package/dist/tools-http/types.d.ts +116 -0
- package/dist/tools-shell/define.d.ts +23 -0
- package/dist/tools-shell/events.d.ts +38 -0
- package/dist/tools-shell/exec.d.ts +37 -0
- package/dist/tools-shell/index.d.ts +30 -0
- package/dist/tools-shell/index.js +327 -0
- package/dist/tools-shell/policy.d.ts +42 -0
- package/dist/tools-shell/types.d.ts +121 -0
- package/dist/tools-web/define.d.ts +11 -0
- package/dist/tools-web/html.d.ts +22 -0
- package/dist/tools-web/index.d.ts +21 -0
- package/dist/tools-web/index.js +472 -0
- package/dist/tools-web/types.d.ts +81 -0
- package/docs/README.md +58 -10
- package/docs/api/.nojekyll +1 -0
- package/docs/api/assets/hierarchy.js +1 -0
- package/docs/api/assets/highlight.css +99 -0
- package/docs/api/assets/icons.js +18 -0
- package/docs/api/assets/icons.svg +1 -0
- package/docs/api/assets/main.js +60 -0
- package/docs/api/assets/navigation.js +1 -0
- package/docs/api/assets/search.js +1 -0
- package/docs/api/assets/style.css +1633 -0
- package/docs/api/classes/errors.AgentError.html +47 -0
- package/docs/api/classes/errors.CancelledError.html +46 -0
- package/docs/api/classes/errors.ContextWindowError.html +48 -0
- package/docs/api/classes/errors.ExecutionError.html +46 -0
- package/docs/api/classes/errors.FilesystemPolicyError.html +48 -0
- package/docs/api/classes/errors.MaxHandoffsExceededError.html +47 -0
- package/docs/api/classes/errors.MaxStepsExceededError.html +47 -0
- package/docs/api/classes/errors.ProviderError.html +47 -0
- package/docs/api/classes/errors.SchemaValidationError.html +47 -0
- package/docs/api/classes/errors.ShellPolicyError.html +50 -0
- package/docs/api/classes/errors.ToolError.html +47 -0
- package/docs/api/classes/errors.ToolValidationError.html +48 -0
- package/docs/api/classes/index.InMemorySessionStore.html +11 -0
- package/docs/api/classes/index.Secret.html +20 -0
- package/docs/api/classes/providers.StreamAccumulator.html +8 -0
- package/docs/api/classes/session-stores.FilesystemJsonlSessionStore.html +13 -0
- package/docs/api/classes/session-stores.ForgeDataSessionStore.html +14 -0
- package/docs/api/classes/session-stores.RedisSessionStore.html +12 -0
- package/docs/api/classes/tools-http.HttpPolicyError.html +41 -0
- package/docs/api/functions/agent.createToolRegistry.html +3 -0
- package/docs/api/functions/agent.handoffProviderTools.html +3 -0
- package/docs/api/functions/agent.handoffToolName.html +2 -0
- package/docs/api/functions/agent.resolveHandoffTargets.html +8 -0
- package/docs/api/functions/context.applyContextWindow.html +5 -0
- package/docs/api/functions/context.estimateTokens.html +3 -0
- package/docs/api/functions/context.resolveContext.html +5 -0
- package/docs/api/functions/events.createRunTelemetry.html +3 -0
- package/docs/api/functions/events.eventFields.html +4 -0
- package/docs/api/functions/events.eventPayload.html +5 -0
- package/docs/api/functions/execution.addUsage.html +2 -0
- package/docs/api/functions/execution.emptyUsage.html +2 -0
- package/docs/api/functions/index.asSchema.html +4 -0
- package/docs/api/functions/index.asTool.html +8 -0
- package/docs/api/functions/index.assistant.html +2 -0
- package/docs/api/functions/index.createAgentRegistry.html +5 -0
- package/docs/api/functions/index.createAnthropic.html +5 -0
- package/docs/api/functions/index.createEventHub.html +2 -0
- package/docs/api/functions/index.createGoogle.html +5 -0
- package/docs/api/functions/index.createOpenAI.html +5 -0
- package/docs/api/functions/index.createOpenAICompatible.html +7 -0
- package/docs/api/functions/index.createSession.html +3 -0
- package/docs/api/functions/index.defineAgent.html +7 -0
- package/docs/api/functions/index.defineTool.html +7 -0
- package/docs/api/functions/index.dynamicContext.html +2 -0
- package/docs/api/functions/index.fromJsonSchema.html +3 -0
- package/docs/api/functions/index.isSecret.html +4 -0
- package/docs/api/functions/index.loggingSubscriber.html +4 -0
- package/docs/api/functions/index.messageBusSubscriber.html +6 -0
- package/docs/api/functions/index.normalizeContent.html +2 -0
- package/docs/api/functions/index.resolveSecret.html +4 -0
- package/docs/api/functions/index.runAgent.html +19 -0
- package/docs/api/functions/index.staticContext.html +3 -0
- package/docs/api/functions/index.summarizeOldest.html +4 -0
- package/docs/api/functions/index.system.html +2 -0
- package/docs/api/functions/index.text.html +2 -0
- package/docs/api/functions/index.toJsonSchema.html +2 -0
- package/docs/api/functions/index.toolResult.html +2 -0
- package/docs/api/functions/index.truncateOldest.html +5 -0
- package/docs/api/functions/index.user.html +2 -0
- package/docs/api/functions/index.validateJsonSchema.html +3 -0
- package/docs/api/functions/lifecycle.agentRuntimeComponent.html +5 -0
- package/docs/api/functions/providers.collectStream.html +2 -0
- package/docs/api/functions/providers.createProvider.html +4 -0
- package/docs/api/functions/providers.createProviderHttp.html +3 -0
- package/docs/api/functions/providers.defaultProviderResilience.html +3 -0
- package/docs/api/functions/providers.openSseStream.html +6 -0
- package/docs/api/functions/providers.parseSse.html +2 -0
- package/docs/api/functions/providers.toProviderError.html +2 -0
- package/docs/api/functions/session-stores.createPostgresSessionStore.html +1 -0
- package/docs/api/functions/session-stores.createSqliteSessionStore.html +1 -0
- package/docs/api/functions/session-stores.isCloseableSessionStore.html +1 -0
- package/docs/api/functions/session-stores.isVersionedSessionStore.html +1 -0
- package/docs/api/functions/session-stores.migrateSessionStore.html +1 -0
- package/docs/api/functions/session-stores.withSessionStoreHooks.html +2 -0
- package/docs/api/functions/testing.byteStreamOf.html +2 -0
- package/docs/api/functions/testing.collectProviderStream.html +2 -0
- package/docs/api/functions/testing.conversation.html +2 -0
- package/docs/api/functions/testing.expectValid.html +3 -0
- package/docs/api/functions/testing.inMemorySessionStore.html +2 -0
- package/docs/api/functions/testing.jsonFetch.html +3 -0
- package/docs/api/functions/testing.mockProvider.html +3 -0
- package/docs/api/functions/testing.scriptedProvider.html +4 -0
- package/docs/api/functions/testing.sseFetch.html +3 -0
- package/docs/api/functions/testing.textResult.html +3 -0
- package/docs/api/functions/testing.toolCallResult.html +3 -0
- package/docs/api/functions/testing_conformance.runProviderConformance.html +3 -0
- package/docs/api/functions/tools-fs.filesystemTools.html +1 -0
- package/docs/api/functions/tools-http.createHttpToolClient.html +2 -0
- package/docs/api/functions/tools-http.httpTools.html +2 -0
- package/docs/api/functions/tools-shell.shellTools.html +4 -0
- package/docs/api/functions/tools-web.webTools.html +2 -0
- package/docs/api/functions/tools.renderToolContent.html +6 -0
- package/docs/api/functions/tools.toProviderTool.html +3 -0
- package/docs/api/functions/tools.toToolResultMessage.html +4 -0
- package/docs/api/hierarchy.html +1 -0
- package/docs/api/index.html +1 -0
- package/docs/api/interfaces/agent.ToolRegistry.html +8 -0
- package/docs/api/interfaces/errors.SchemaIssue.html +4 -0
- package/docs/api/interfaces/events.RunTelemetry.html +10 -0
- package/docs/api/interfaces/events.SpanHandle.html +6 -0
- package/docs/api/interfaces/index.AgentDefinition.html +16 -0
- package/docs/api/interfaces/index.AgentHooks.html +21 -0
- package/docs/api/interfaces/index.AgentRegistry.html +16 -0
- package/docs/api/interfaces/index.AnthropicOptions.html +13 -0
- package/docs/api/interfaces/index.AsToolOptions.html +13 -0
- package/docs/api/interfaces/index.CompletionRequest.html +30 -0
- package/docs/api/interfaces/index.CompletionResult.html +14 -0
- package/docs/api/interfaces/index.ContextItem.html +6 -0
- package/docs/api/interfaces/index.ContextProvider.html +5 -0
- package/docs/api/interfaces/index.ContextStrategy.html +8 -0
- package/docs/api/interfaces/index.ContextStrategyContext.html +8 -0
- package/docs/api/interfaces/index.ContextWindowOptions.html +8 -0
- package/docs/api/interfaces/index.CreateSessionOptions.html +10 -0
- package/docs/api/interfaces/index.EngineContext.html +10 -0
- package/docs/api/interfaces/index.EventHub.html +4 -0
- package/docs/api/interfaces/index.EventHubOptions.html +8 -0
- package/docs/api/interfaces/index.GenerationSettings.html +12 -0
- package/docs/api/interfaces/index.GoogleOptions.html +11 -0
- package/docs/api/interfaces/index.ImagePart.html +5 -0
- package/docs/api/interfaces/index.InstructionContext.html +9 -0
- package/docs/api/interfaces/index.JsonSchema.html +18 -0
- package/docs/api/interfaces/index.LoggingSubscriberOptions.html +4 -0
- package/docs/api/interfaces/index.Message.html +8 -0
- package/docs/api/interfaces/index.MessageBusSubscriberOptions.html +4 -0
- package/docs/api/interfaces/index.OpenAICompatibleOptions.html +16 -0
- package/docs/api/interfaces/index.OpenAIOptions.html +16 -0
- package/docs/api/interfaces/index.Provider.html +11 -0
- package/docs/api/interfaces/index.ProviderCapabilities.html +9 -0
- package/docs/api/interfaces/index.ProviderTool.html +6 -0
- package/docs/api/interfaces/index.ResponseSchema.html +6 -0
- package/docs/api/interfaces/index.RunBridge.html +10 -0
- package/docs/api/interfaces/index.RunOptions.html +39 -0
- package/docs/api/interfaces/index.RunResult.html +20 -0
- package/docs/api/interfaces/index.Schema.html +13 -0
- package/docs/api/interfaces/index.Session.html +13 -0
- package/docs/api/interfaces/index.SessionState.html +5 -0
- package/docs/api/interfaces/index.SessionStore.html +15 -0
- package/docs/api/interfaces/index.TextPart.html +4 -0
- package/docs/api/interfaces/index.ToolCall.html +9 -0
- package/docs/api/interfaces/index.ToolCallPart.html +6 -0
- package/docs/api/interfaces/index.ToolContext.html +21 -0
- package/docs/api/interfaces/index.ToolDefinition.html +14 -0
- package/docs/api/interfaces/index.ToolFailure.html +9 -0
- package/docs/api/interfaces/index.ToolResultPart.html +8 -0
- package/docs/api/interfaces/index.ToolSpec.html +6 -0
- package/docs/api/interfaces/index.ToolSuccess.html +6 -0
- package/docs/api/interfaces/index.Usage.html +9 -0
- package/docs/api/interfaces/lifecycle.AgentRuntimeOptions.html +17 -0
- package/docs/api/interfaces/providers.AdapterSpec.html +17 -0
- package/docs/api/interfaces/providers.ProviderHttpOptions.html +14 -0
- package/docs/api/interfaces/providers.SseMessage.html +6 -0
- package/docs/api/interfaces/providers.SseRequest.html +8 -0
- package/docs/api/interfaces/runtime.Logger.html +22 -0
- package/docs/api/interfaces/runtime.Telemetry.html +9 -0
- package/docs/api/interfaces/schema.OptionalSchema.html +13 -0
- package/docs/api/interfaces/session-stores.CloseableSessionStore.html +11 -0
- package/docs/api/interfaces/session-stores.CreatePostgresSessionStoreOptions.html +6 -0
- package/docs/api/interfaces/session-stores.CreateSqliteSessionStoreOptions.html +7 -0
- package/docs/api/interfaces/session-stores.FilesystemJsonlSessionStoreOptions.html +3 -0
- package/docs/api/interfaces/session-stores.ForgeDataSessionStoreOptions.html +5 -0
- package/docs/api/interfaces/session-stores.RedisSessionStoreClient.html +9 -0
- package/docs/api/interfaces/session-stores.RedisSessionStoreOptions.html +4 -0
- package/docs/api/interfaces/session-stores.RedisSessionStoreTransaction.html +6 -0
- package/docs/api/interfaces/session-stores.SessionArchiveRecord.html +7 -0
- package/docs/api/interfaces/session-stores.SessionArchiver.html +2 -0
- package/docs/api/interfaces/session-stores.SessionCompactionResult.html +3 -0
- package/docs/api/interfaces/session-stores.SessionCompactor.html +3 -0
- package/docs/api/interfaces/session-stores.SessionStoreCodec.html +6 -0
- package/docs/api/interfaces/session-stores.SessionStoreHookContext.html +3 -0
- package/docs/api/interfaces/session-stores.SessionStoreHooks.html +3 -0
- package/docs/api/interfaces/session-stores.VersionedSessionStore.html +11 -0
- package/docs/api/interfaces/testing.MockProviderOptions.html +12 -0
- package/docs/api/interfaces/testing.RecordedCall.html +4 -0
- package/docs/api/interfaces/testing.RecordingFetch.html +4 -0
- package/docs/api/interfaces/testing_conformance.ConformanceFixtures.html +12 -0
- package/docs/api/interfaces/testing_conformance.ConformanceOptions.html +10 -0
- package/docs/api/interfaces/testing_conformance.ConformanceTestApi.html +4 -0
- package/docs/api/interfaces/testing_conformance.ProviderIO.html +7 -0
- package/docs/api/interfaces/tools-fs.ApplyPatchArgs.html +6 -0
- package/docs/api/interfaces/tools-fs.DiffStatusArgs.html +5 -0
- package/docs/api/interfaces/tools-fs.EditRangeArgs.html +7 -0
- package/docs/api/interfaces/tools-fs.EditReplaceArgs.html +7 -0
- package/docs/api/interfaces/tools-fs.FilesystemTools.html +13 -0
- package/docs/api/interfaces/tools-fs.FilesystemToolsConfig.html +12 -0
- package/docs/api/interfaces/tools-fs.FindFilesArgs.html +7 -0
- package/docs/api/interfaces/tools-fs.OpenWindowArgs.html +5 -0
- package/docs/api/interfaces/tools-fs.ReadArgs.html +9 -0
- package/docs/api/interfaces/tools-fs.RepoMapArgs.html +7 -0
- package/docs/api/interfaces/tools-fs.SearchSemanticArgs.html +8 -0
- package/docs/api/interfaces/tools-fs.SearchTextArgs.html +11 -0
- package/docs/api/interfaces/tools-fs.SymbolInfo.html +7 -0
- package/docs/api/interfaces/tools-fs.SymbolsArgs.html +5 -0
- package/docs/api/interfaces/tools-fs.ValidationCommandRequest.html +4 -0
- package/docs/api/interfaces/tools-fs.ValidationCommandResult.html +6 -0
- package/docs/api/interfaces/tools-fs.ValidationOptions.html +4 -0
- package/docs/api/interfaces/tools-fs.WriteFileArgs.html +6 -0
- package/docs/api/interfaces/tools-http.HeaderEntry.html +4 -0
- package/docs/api/interfaces/tools-http.HttpClientRequest.html +11 -0
- package/docs/api/interfaces/tools-http.HttpPolicy.html +13 -0
- package/docs/api/interfaces/tools-http.HttpRequestResult.html +17 -0
- package/docs/api/interfaces/tools-http.HttpRetryOptions.html +10 -0
- package/docs/api/interfaces/tools-http.HttpToolClient.html +5 -0
- package/docs/api/interfaces/tools-http.HttpTools.html +4 -0
- package/docs/api/interfaces/tools-http.HttpToolsConfig.html +38 -0
- package/docs/api/interfaces/tools-shell.ApprovalDecision.html +5 -0
- package/docs/api/interfaces/tools-shell.CommandRequest.html +14 -0
- package/docs/api/interfaces/tools-shell.CommandResult.html +21 -0
- package/docs/api/interfaces/tools-shell.EnvPolicy.html +9 -0
- package/docs/api/interfaces/tools-shell.ShellPolicy.html +7 -0
- package/docs/api/interfaces/tools-shell.ShellTools.html +6 -0
- package/docs/api/interfaces/tools-shell.ShellToolsConfig.html +26 -0
- package/docs/api/interfaces/tools-web.Citation.html +6 -0
- package/docs/api/interfaces/tools-web.SearchProvider.html +3 -0
- package/docs/api/interfaces/tools-web.SearchRequest.html +4 -0
- package/docs/api/interfaces/tools-web.SearchResult.html +7 -0
- package/docs/api/interfaces/tools-web.SourceMetadata.html +10 -0
- package/docs/api/interfaces/tools-web.WebTools.html +6 -0
- package/docs/api/interfaces/tools-web.WebToolsConfig.html +56 -0
- package/docs/api/modules/agent.html +5 -0
- package/docs/api/modules/context.html +5 -0
- package/docs/api/modules/errors.html +8 -0
- package/docs/api/modules/events.html +16 -0
- package/docs/api/modules/execution.html +4 -0
- package/docs/api/modules/index.html +16 -0
- package/docs/api/modules/lifecycle.html +6 -0
- package/docs/api/modules/messages.html +3 -0
- package/docs/api/modules/providers.html +10 -0
- package/docs/api/modules/runtime.html +4 -0
- package/docs/api/modules/schema.html +5 -0
- package/docs/api/modules/session-stores.html +6 -0
- package/docs/api/modules/session.html +4 -0
- package/docs/api/modules/testing.html +4 -0
- package/docs/api/modules/testing_conformance.html +21 -0
- package/docs/api/modules/tools-fs.html +9 -0
- package/docs/api/modules/tools-http.html +8 -0
- package/docs/api/modules/tools-shell.html +12 -0
- package/docs/api/modules/tools-web.html +7 -0
- package/docs/api/modules/tools.html +4 -0
- package/docs/api/types/events.Attrs.html +2 -0
- package/docs/api/types/index.AnyRunOptions.html +3 -0
- package/docs/api/types/index.BufferedRunOptions.html +2 -0
- package/docs/api/types/index.ContentPart.html +2 -0
- package/docs/api/types/index.FinishReason.html +2 -0
- package/docs/api/types/index.Infer.html +2 -0
- package/docs/api/types/index.Instructions.html +5 -0
- package/docs/api/types/index.LogLevel.html +2 -0
- package/docs/api/types/index.Role.html +2 -0
- package/docs/api/types/index.RunEvent.html +30 -0
- package/docs/api/types/index.RunHandle.html +7 -0
- package/docs/api/types/index.RunInput.html +2 -0
- package/docs/api/types/index.RunSubscriber.html +4 -0
- package/docs/api/types/index.SafeParseResult.html +2 -0
- package/docs/api/types/index.StreamEvent.html +8 -0
- package/docs/api/types/index.StreamingRunOptions.html +2 -0
- package/docs/api/types/index.TelemetryHandle.html +2 -0
- package/docs/api/types/index.TokenCounter.html +2 -0
- package/docs/api/types/index.ToolChoice.html +2 -0
- package/docs/api/types/index.ToolResult.html +2 -0
- package/docs/api/types/lifecycle.ProviderProbe.html +2 -0
- package/docs/api/types/session-stores.SessionStoreHookOperation.html +1 -0
- package/docs/api/types/testing_conformance.MakeProvider.html +2 -0
- package/docs/api/types/tools-fs.SymbolKind.html +1 -0
- package/docs/api/types/tools-http.HostPattern.html +2 -0
- package/docs/api/types/tools-shell.CommandPattern.html +2 -0
- package/docs/api/types/tools-web.RobotsPolicy.html +2 -0
- package/docs/api/variables/events.SPAN_PROVIDER.html +2 -0
- package/docs/api/variables/events.SPAN_RUN.html +2 -0
- package/docs/api/variables/events.SPAN_TOOL.html +2 -0
- package/docs/api/variables/execution.DEFAULT_MAX_HANDOFFS.html +2 -0
- package/docs/api/variables/execution.DEFAULT_MAX_STEPS.html +2 -0
- package/docs/api/variables/index.s.html +11 -0
- package/docs/api/variables/providers.DEFAULT_TIMEOUT_MS.html +2 -0
- package/docs/api/variables/session-stores.SESSION_STORE_SCHEMA_VERSION.html +1 -0
- package/docs/api/variables/session-stores.jsonSessionStoreCodec.html +2 -0
- package/docs/api/variables/tools-http.HTTP_EVENT.html +2 -0
- package/docs/api/variables/tools-shell.SHELL_EVENT.html +2 -0
- package/docs/events-and-telemetry.md +68 -0
- package/docs/execution.md +63 -0
- package/docs/getting-started.md +73 -0
- package/docs/multi-agent.md +52 -0
- package/docs/optional-tool-packs.md +93 -0
- package/docs/providers.md +68 -0
- package/docs/retrieval.md +83 -0
- package/docs/sessions-and-context.md +82 -0
- package/docs/testing-and-lifecycle.md +60 -0
- package/docs/tools.md +69 -0
- package/examples/01-minimal-agent.ts +19 -0
- package/examples/02-custom-tool.ts +32 -0
- package/examples/03-streaming.ts +46 -0
- package/examples/04-sessions-context.ts +40 -0
- package/examples/05-events-subscribers.ts +35 -0
- package/examples/06-multi-agent-handoff.ts +27 -0
- package/examples/07-sub-agent-tool.ts +26 -0
- package/examples/08-testing-agent.ts +31 -0
- package/examples/09-tools-filesystem.ts +49 -0
- package/examples/10-tools-http-web.ts +74 -0
- package/examples/11-shell-tools.ts +39 -0
- package/examples/12-provider-openai.ts +24 -0
- package/examples/13-lifecycle.ts +37 -0
- package/examples/14-retrieval.ts +65 -0
- package/examples/incident-analysis.ts +52 -0
- package/package.json +78 -4
- package/dist/index-02s1fjxr.js +0 -226
|
@@ -0,0 +1,1382 @@
|
|
|
1
|
+
import"../index-37x76zdn.js";
|
|
2
|
+
|
|
3
|
+
// src/session-stores/codec.ts
|
|
4
|
+
function decodeObject(payload) {
|
|
5
|
+
return JSON.parse(payload);
|
|
6
|
+
}
|
|
7
|
+
var jsonSessionStoreCodec = {
|
|
8
|
+
encodeMessage(message) {
|
|
9
|
+
return JSON.stringify(message);
|
|
10
|
+
},
|
|
11
|
+
decodeMessage(payload) {
|
|
12
|
+
return decodeObject(payload);
|
|
13
|
+
},
|
|
14
|
+
encodeMetadata(metadata) {
|
|
15
|
+
return metadata === undefined ? undefined : JSON.stringify(metadata);
|
|
16
|
+
},
|
|
17
|
+
decodeMetadata(payload) {
|
|
18
|
+
return payload === undefined ? undefined : decodeObject(payload);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
async function encodeMetadata(codec, metadata) {
|
|
22
|
+
if (codec.encodeMetadata !== undefined)
|
|
23
|
+
return codec.encodeMetadata(metadata);
|
|
24
|
+
return jsonSessionStoreCodec.encodeMetadata(metadata);
|
|
25
|
+
}
|
|
26
|
+
async function decodeMetadata(codec, payload) {
|
|
27
|
+
const value = payload ?? undefined;
|
|
28
|
+
if (codec.decodeMetadata !== undefined)
|
|
29
|
+
return codec.decodeMetadata(value);
|
|
30
|
+
return jsonSessionStoreCodec.decodeMetadata(value);
|
|
31
|
+
}
|
|
32
|
+
async function encodeMessages(codec, messages) {
|
|
33
|
+
const encoded = [];
|
|
34
|
+
for (const message of messages)
|
|
35
|
+
encoded.push(await codec.encodeMessage(message));
|
|
36
|
+
return encoded;
|
|
37
|
+
}
|
|
38
|
+
async function decodeMessages(codec, payloads) {
|
|
39
|
+
const messages = [];
|
|
40
|
+
for (const payload of payloads)
|
|
41
|
+
messages.push(await codec.decodeMessage(payload));
|
|
42
|
+
return messages;
|
|
43
|
+
}
|
|
44
|
+
// node_modules/@infinityi/forge/dist/index-zxk5c56c.js
|
|
45
|
+
class DataError extends Error {
|
|
46
|
+
constructor(message, options) {
|
|
47
|
+
super(message, options);
|
|
48
|
+
this.name = "DataError";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
class QueryError extends DataError {
|
|
53
|
+
sql;
|
|
54
|
+
params;
|
|
55
|
+
dialect;
|
|
56
|
+
constructor(message, options) {
|
|
57
|
+
super(message, options);
|
|
58
|
+
this.name = "QueryError";
|
|
59
|
+
this.sql = options.sql;
|
|
60
|
+
this.params = options.params;
|
|
61
|
+
this.dialect = options.dialect;
|
|
62
|
+
}
|
|
63
|
+
toJSON() {
|
|
64
|
+
return {
|
|
65
|
+
name: this.name,
|
|
66
|
+
message: this.message,
|
|
67
|
+
dialect: this.dialect,
|
|
68
|
+
sql: this.sql,
|
|
69
|
+
params: "[REDACTED]"
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
class TransactionError extends DataError {
|
|
74
|
+
state;
|
|
75
|
+
constructor(message, options) {
|
|
76
|
+
super(message, options);
|
|
77
|
+
this.name = "TransactionError";
|
|
78
|
+
if (options?.state !== undefined)
|
|
79
|
+
this.state = options.state;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
class TenantError extends DataError {
|
|
83
|
+
tenantId;
|
|
84
|
+
constructor(message, options) {
|
|
85
|
+
super(message, options);
|
|
86
|
+
this.name = "TenantError";
|
|
87
|
+
if (options?.tenantId !== undefined)
|
|
88
|
+
this.tenantId = options.tenantId;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// node_modules/@infinityi/forge/dist/data/index.js
|
|
93
|
+
function createDataInstrumentation(options) {
|
|
94
|
+
const histogram = options.telemetry?.meter?.createHistogram("forge_db_query_duration_seconds", {
|
|
95
|
+
description: "Database query execution time.",
|
|
96
|
+
unit: "s"
|
|
97
|
+
});
|
|
98
|
+
return {
|
|
99
|
+
startQuerySpan(query) {
|
|
100
|
+
return options.telemetry?.tracer?.startSpan("db.query", {
|
|
101
|
+
kind: "client",
|
|
102
|
+
attributes: queryAttributes(options, query)
|
|
103
|
+
});
|
|
104
|
+
},
|
|
105
|
+
recordQuerySuccess(query, result, startedAt, span) {
|
|
106
|
+
const durationSeconds = (performance.now() - startedAt) / 1000;
|
|
107
|
+
histogram?.record(durationSeconds, {
|
|
108
|
+
"db.system": options.dialect,
|
|
109
|
+
"db.operation": query.kind
|
|
110
|
+
});
|
|
111
|
+
span?.setAttributes?.({
|
|
112
|
+
"db.rows_affected": Number(result.numAffectedRows),
|
|
113
|
+
"db.duration_ms": durationSeconds * 1000
|
|
114
|
+
});
|
|
115
|
+
span?.setStatus?.({ code: "ok" });
|
|
116
|
+
span?.end?.();
|
|
117
|
+
},
|
|
118
|
+
recordQueryFailure(query, cause, startedAt, span) {
|
|
119
|
+
const durationSeconds = (performance.now() - startedAt) / 1000;
|
|
120
|
+
histogram?.record(durationSeconds, {
|
|
121
|
+
"db.system": options.dialect,
|
|
122
|
+
"db.operation": query.kind
|
|
123
|
+
});
|
|
124
|
+
span?.setAttributes?.({ "db.duration_ms": durationSeconds * 1000 });
|
|
125
|
+
span?.setStatus?.({
|
|
126
|
+
code: "error",
|
|
127
|
+
message: cause instanceof Error ? cause.message : String(cause)
|
|
128
|
+
});
|
|
129
|
+
span?.addEvent?.("exception", {
|
|
130
|
+
"exception.message": cause instanceof Error ? cause.message : String(cause),
|
|
131
|
+
"exception.type": cause instanceof Error ? cause.name : typeof cause
|
|
132
|
+
});
|
|
133
|
+
span?.end?.();
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function queryAttributes(options, query) {
|
|
138
|
+
const attributes = {
|
|
139
|
+
"db.system": options.dialect,
|
|
140
|
+
"db.operation": query.kind,
|
|
141
|
+
"db.statement": query.sql
|
|
142
|
+
};
|
|
143
|
+
if (options.telemetry?.includeParams === true) {
|
|
144
|
+
attributes["db.params"] = JSON.stringify(query.params);
|
|
145
|
+
}
|
|
146
|
+
return attributes;
|
|
147
|
+
}
|
|
148
|
+
function compileNode(dialect, node) {
|
|
149
|
+
switch (node.kind) {
|
|
150
|
+
case "select":
|
|
151
|
+
return compileSelect(dialect, node);
|
|
152
|
+
case "insert":
|
|
153
|
+
return compileInsert(dialect, node);
|
|
154
|
+
case "update":
|
|
155
|
+
return compileUpdate(dialect, node);
|
|
156
|
+
case "delete":
|
|
157
|
+
return compileDelete(dialect, node);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function compileRaw(dialect, query) {
|
|
161
|
+
return {
|
|
162
|
+
sql: rewriteParameterPlaceholders(dialect, query.text, query.params.length),
|
|
163
|
+
params: query.params,
|
|
164
|
+
kind: "raw",
|
|
165
|
+
returning: /\breturning\b/i.test(query.text)
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function compileSelect(dialect, node) {
|
|
169
|
+
const params = [];
|
|
170
|
+
const columns = compileColumns(dialect, node.columns);
|
|
171
|
+
const parts = [`select ${columns} from ${dialect.quoteIdentifier(node.table)}`];
|
|
172
|
+
appendWhere(dialect, parts, params, node.where);
|
|
173
|
+
if (node.orderBy.length > 0) {
|
|
174
|
+
const orderBy = node.orderBy.map((item) => `${dialect.quoteIdentifier(item.column)} ${item.direction}`).join(", ");
|
|
175
|
+
parts.push(`order by ${orderBy}`);
|
|
176
|
+
}
|
|
177
|
+
if (node.limit !== undefined) {
|
|
178
|
+
params.push(node.limit);
|
|
179
|
+
parts.push(`limit ${dialect.placeholder(params.length)}`);
|
|
180
|
+
}
|
|
181
|
+
return { sql: parts.join(" "), params, kind: "select", returning: false };
|
|
182
|
+
}
|
|
183
|
+
function compileInsert(dialect, node) {
|
|
184
|
+
if (node.values.length === 0) {
|
|
185
|
+
throw new Error("insert requires at least one value row");
|
|
186
|
+
}
|
|
187
|
+
const params = [];
|
|
188
|
+
const columns = Object.keys(node.values[0] ?? {});
|
|
189
|
+
if (columns.length === 0) {
|
|
190
|
+
throw new Error("insert value row must contain at least one column");
|
|
191
|
+
}
|
|
192
|
+
const columnSql = columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
|
|
193
|
+
const valuesSql = node.values.map((row) => {
|
|
194
|
+
const placeholders = columns.map((column) => {
|
|
195
|
+
params.push(row[column]);
|
|
196
|
+
return dialect.placeholder(params.length);
|
|
197
|
+
});
|
|
198
|
+
return `(${placeholders.join(", ")})`;
|
|
199
|
+
}).join(", ");
|
|
200
|
+
const parts = [
|
|
201
|
+
`insert into ${dialect.quoteIdentifier(node.table)} (${columnSql}) values ${valuesSql}`
|
|
202
|
+
];
|
|
203
|
+
appendReturning(dialect, parts, node.returning);
|
|
204
|
+
return { sql: parts.join(" "), params, kind: "insert", returning: node.returning !== undefined };
|
|
205
|
+
}
|
|
206
|
+
function compileUpdate(dialect, node) {
|
|
207
|
+
const params = [];
|
|
208
|
+
const columns = Object.keys(node.set);
|
|
209
|
+
if (columns.length === 0) {
|
|
210
|
+
throw new Error("update requires at least one set value");
|
|
211
|
+
}
|
|
212
|
+
const assignments = columns.map((column) => {
|
|
213
|
+
params.push(node.set[column]);
|
|
214
|
+
return `${dialect.quoteIdentifier(column)} = ${dialect.placeholder(params.length)}`;
|
|
215
|
+
});
|
|
216
|
+
const parts = [
|
|
217
|
+
`update ${dialect.quoteIdentifier(node.table)} set ${assignments.join(", ")}`
|
|
218
|
+
];
|
|
219
|
+
appendWhere(dialect, parts, params, node.where);
|
|
220
|
+
appendReturning(dialect, parts, node.returning);
|
|
221
|
+
return { sql: parts.join(" "), params, kind: "update", returning: node.returning !== undefined };
|
|
222
|
+
}
|
|
223
|
+
function compileDelete(dialect, node) {
|
|
224
|
+
const params = [];
|
|
225
|
+
const parts = [`delete from ${dialect.quoteIdentifier(node.table)}`];
|
|
226
|
+
appendWhere(dialect, parts, params, node.where);
|
|
227
|
+
appendReturning(dialect, parts, node.returning);
|
|
228
|
+
return { sql: parts.join(" "), params, kind: "delete", returning: node.returning !== undefined };
|
|
229
|
+
}
|
|
230
|
+
function appendWhere(dialect, parts, params, predicates) {
|
|
231
|
+
if (predicates.length === 0)
|
|
232
|
+
return;
|
|
233
|
+
const sql = predicates.map((predicate) => {
|
|
234
|
+
params.push(predicate.value);
|
|
235
|
+
return `${dialect.quoteIdentifier(predicate.column)} ${predicate.operator} ${dialect.placeholder(params.length)}`;
|
|
236
|
+
});
|
|
237
|
+
parts.push(`where ${sql.join(" and ")}`);
|
|
238
|
+
}
|
|
239
|
+
function appendReturning(dialect, parts, returning) {
|
|
240
|
+
if (returning === undefined)
|
|
241
|
+
return;
|
|
242
|
+
parts.push(`returning ${compileColumns(dialect, returning)}`);
|
|
243
|
+
}
|
|
244
|
+
function compileColumns(dialect, columns) {
|
|
245
|
+
if (columns === "*")
|
|
246
|
+
return "*";
|
|
247
|
+
if (columns.length === 0)
|
|
248
|
+
return "*";
|
|
249
|
+
return columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
|
|
250
|
+
}
|
|
251
|
+
function rewriteParameterPlaceholders(dialect, text, paramCount) {
|
|
252
|
+
if (paramCount === 0)
|
|
253
|
+
return text;
|
|
254
|
+
let next = 0;
|
|
255
|
+
return text.replaceAll("?", () => {
|
|
256
|
+
next += 1;
|
|
257
|
+
return next <= paramCount ? dialect.placeholder(next) : "?";
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
class ExecutableQuery {
|
|
262
|
+
db;
|
|
263
|
+
compileFn;
|
|
264
|
+
constructor(db, compileFn) {
|
|
265
|
+
this.db = db;
|
|
266
|
+
this.compileFn = compileFn;
|
|
267
|
+
}
|
|
268
|
+
compile() {
|
|
269
|
+
try {
|
|
270
|
+
return this.compileFn();
|
|
271
|
+
} catch (cause) {
|
|
272
|
+
if (cause instanceof DataError)
|
|
273
|
+
throw cause;
|
|
274
|
+
throw new DataError("Failed to compile query", { cause });
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
execute() {
|
|
278
|
+
return this.db.execute(this.compile());
|
|
279
|
+
}
|
|
280
|
+
async executeTakeFirst() {
|
|
281
|
+
const result = await this.execute();
|
|
282
|
+
return result.rows[0];
|
|
283
|
+
}
|
|
284
|
+
async executeTakeFirstOrThrow() {
|
|
285
|
+
const row = await this.executeTakeFirst();
|
|
286
|
+
if (row === undefined) {
|
|
287
|
+
throw new DataError("Expected query to return at least one row");
|
|
288
|
+
}
|
|
289
|
+
return row;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
class DeleteBuilder extends ExecutableQuery {
|
|
294
|
+
dialect;
|
|
295
|
+
node;
|
|
296
|
+
constructor(db, dialect, node) {
|
|
297
|
+
super(db, () => compileNode(dialect, node));
|
|
298
|
+
this.dialect = dialect;
|
|
299
|
+
this.node = node;
|
|
300
|
+
}
|
|
301
|
+
where(column, operator, value) {
|
|
302
|
+
return new DeleteBuilder(this.db, this.dialect, {
|
|
303
|
+
...this.node,
|
|
304
|
+
where: [...this.node.where, { column, operator, value }]
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
returning(columns) {
|
|
308
|
+
return new ExecutableQuery(this.db, () => compileNode(this.dialect, { ...this.node, returning: columns }));
|
|
309
|
+
}
|
|
310
|
+
returningAll() {
|
|
311
|
+
return new ExecutableQuery(this.db, () => compileNode(this.dialect, { ...this.node, returning: "*" }));
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
function createDeleteBuilder(db, dialect, table, tenant) {
|
|
315
|
+
return new DeleteBuilder(db, dialect, {
|
|
316
|
+
kind: "delete",
|
|
317
|
+
table,
|
|
318
|
+
where: tenant === undefined ? [] : [{ column: tenant.column, operator: "=", value: tenant.id }]
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
class InsertBuilder extends ExecutableQuery {
|
|
323
|
+
dialect;
|
|
324
|
+
node;
|
|
325
|
+
tenant;
|
|
326
|
+
constructor(db, dialect, node, tenant) {
|
|
327
|
+
super(db, () => compileNode(dialect, node));
|
|
328
|
+
this.dialect = dialect;
|
|
329
|
+
this.node = node;
|
|
330
|
+
this.tenant = tenant;
|
|
331
|
+
}
|
|
332
|
+
values(value) {
|
|
333
|
+
const rows = (Array.isArray(value) ? value : [value]).map((row) => applyTenantValue(row, this.tenant));
|
|
334
|
+
return new InsertBuilder(this.db, this.dialect, {
|
|
335
|
+
...this.node,
|
|
336
|
+
values: rows
|
|
337
|
+
}, this.tenant);
|
|
338
|
+
}
|
|
339
|
+
returning(columns) {
|
|
340
|
+
return new ExecutableQuery(this.db, () => compileNode(this.dialect, { ...this.node, returning: columns }));
|
|
341
|
+
}
|
|
342
|
+
returningAll() {
|
|
343
|
+
return new ExecutableQuery(this.db, () => compileNode(this.dialect, { ...this.node, returning: "*" }));
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
function createInsertBuilder(db, dialect, table, tenant) {
|
|
347
|
+
return new InsertBuilder(db, dialect, {
|
|
348
|
+
kind: "insert",
|
|
349
|
+
table,
|
|
350
|
+
values: []
|
|
351
|
+
}, tenant);
|
|
352
|
+
}
|
|
353
|
+
function applyTenantValue(row, tenant) {
|
|
354
|
+
if (tenant === undefined)
|
|
355
|
+
return row;
|
|
356
|
+
const current = row[tenant.column];
|
|
357
|
+
if (current !== undefined && current !== tenant.id) {
|
|
358
|
+
throw new TenantError("Insert row tenant does not match scoped tenant", {
|
|
359
|
+
tenantId: tenant.id
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
return { ...row, [tenant.column]: tenant.id };
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
class SelectBuilder extends ExecutableQuery {
|
|
366
|
+
dialect;
|
|
367
|
+
node;
|
|
368
|
+
constructor(db, dialect, node) {
|
|
369
|
+
super(db, () => compileNode(dialect, node));
|
|
370
|
+
this.dialect = dialect;
|
|
371
|
+
this.node = node;
|
|
372
|
+
}
|
|
373
|
+
select(columns) {
|
|
374
|
+
return new SelectBuilder(this.db, this.dialect, { ...this.node, columns });
|
|
375
|
+
}
|
|
376
|
+
where(column, operator, value) {
|
|
377
|
+
return new SelectBuilder(this.db, this.dialect, {
|
|
378
|
+
...this.node,
|
|
379
|
+
where: [...this.node.where, { column, operator, value }]
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
orderBy(column, direction = "asc") {
|
|
383
|
+
return new SelectBuilder(this.db, this.dialect, {
|
|
384
|
+
...this.node,
|
|
385
|
+
orderBy: [...this.node.orderBy, { column, direction }]
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
limit(count) {
|
|
389
|
+
return new SelectBuilder(this.db, this.dialect, {
|
|
390
|
+
...this.node,
|
|
391
|
+
limit: count
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
function createSelectBuilder(db, dialect, table, tenant) {
|
|
396
|
+
const node = {
|
|
397
|
+
kind: "select",
|
|
398
|
+
table,
|
|
399
|
+
columns: "*",
|
|
400
|
+
where: tenant === undefined ? [] : [{ column: tenant.column, operator: "=", value: tenant.id }],
|
|
401
|
+
orderBy: []
|
|
402
|
+
};
|
|
403
|
+
return new SelectBuilder(db, dialect, node);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
class UpdateBuilder extends ExecutableQuery {
|
|
407
|
+
dialect;
|
|
408
|
+
node;
|
|
409
|
+
tenant;
|
|
410
|
+
constructor(db, dialect, node, tenant) {
|
|
411
|
+
super(db, () => compileNode(dialect, node));
|
|
412
|
+
this.dialect = dialect;
|
|
413
|
+
this.node = node;
|
|
414
|
+
this.tenant = tenant;
|
|
415
|
+
}
|
|
416
|
+
set(value) {
|
|
417
|
+
const set = validateTenantSet(value, this.tenant);
|
|
418
|
+
return new UpdateBuilder(this.db, this.dialect, {
|
|
419
|
+
...this.node,
|
|
420
|
+
set: { ...this.node.set, ...set }
|
|
421
|
+
}, this.tenant);
|
|
422
|
+
}
|
|
423
|
+
where(column, operator, value) {
|
|
424
|
+
return new UpdateBuilder(this.db, this.dialect, {
|
|
425
|
+
...this.node,
|
|
426
|
+
where: [...this.node.where, { column, operator, value }]
|
|
427
|
+
}, this.tenant);
|
|
428
|
+
}
|
|
429
|
+
returning(columns) {
|
|
430
|
+
return new ExecutableQuery(this.db, () => compileNode(this.dialect, { ...this.node, returning: columns }));
|
|
431
|
+
}
|
|
432
|
+
returningAll() {
|
|
433
|
+
return new ExecutableQuery(this.db, () => compileNode(this.dialect, { ...this.node, returning: "*" }));
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
function createUpdateBuilder(db, dialect, table, tenant) {
|
|
437
|
+
return new UpdateBuilder(db, dialect, {
|
|
438
|
+
kind: "update",
|
|
439
|
+
table,
|
|
440
|
+
set: {},
|
|
441
|
+
where: tenant === undefined ? [] : [{ column: tenant.column, operator: "=", value: tenant.id }]
|
|
442
|
+
}, tenant);
|
|
443
|
+
}
|
|
444
|
+
function validateTenantSet(value, tenant) {
|
|
445
|
+
if (tenant === undefined)
|
|
446
|
+
return value;
|
|
447
|
+
const current = value[tenant.column];
|
|
448
|
+
if (current !== undefined && current !== tenant.id) {
|
|
449
|
+
throw new TenantError("Update tenant value does not match scoped tenant", {
|
|
450
|
+
tenantId: tenant.id
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
return value;
|
|
454
|
+
}
|
|
455
|
+
function sql(strings, ...values) {
|
|
456
|
+
let text = "";
|
|
457
|
+
const params = [];
|
|
458
|
+
for (let index = 0;index < strings.length; index += 1) {
|
|
459
|
+
text += strings[index] ?? "";
|
|
460
|
+
if (index >= values.length)
|
|
461
|
+
continue;
|
|
462
|
+
const value = values[index];
|
|
463
|
+
if (isSqlFragment(value)) {
|
|
464
|
+
text += value.text;
|
|
465
|
+
params.push(...value.params);
|
|
466
|
+
} else {
|
|
467
|
+
text += "?";
|
|
468
|
+
params.push(value);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
return Object.freeze({ text, params });
|
|
472
|
+
}
|
|
473
|
+
function raw(text) {
|
|
474
|
+
return Object.freeze({ text, params: [] });
|
|
475
|
+
}
|
|
476
|
+
function isSqlFragment(value) {
|
|
477
|
+
return typeof value === "object" && value !== null && typeof value.text === "string" && Array.isArray(value.params);
|
|
478
|
+
}
|
|
479
|
+
function createDb(options) {
|
|
480
|
+
const instrumentation = createDataInstrumentation({
|
|
481
|
+
dialect: options.dialect.name,
|
|
482
|
+
telemetry: options.telemetry
|
|
483
|
+
});
|
|
484
|
+
const executeQuery = async (query) => {
|
|
485
|
+
const span = instrumentation.startQuerySpan(query);
|
|
486
|
+
const startedAt = performance.now();
|
|
487
|
+
try {
|
|
488
|
+
const result = await options.driver.execute(query);
|
|
489
|
+
const normalized = normalizeResult(query, result);
|
|
490
|
+
instrumentation.recordQuerySuccess(query, normalized, startedAt, span);
|
|
491
|
+
return normalized;
|
|
492
|
+
} catch (cause) {
|
|
493
|
+
instrumentation.recordQueryFailure(query, cause, startedAt, span);
|
|
494
|
+
if (cause instanceof QueryError)
|
|
495
|
+
throw cause;
|
|
496
|
+
throw new QueryError("Data query failed", {
|
|
497
|
+
cause,
|
|
498
|
+
sql: query.sql,
|
|
499
|
+
params: query.params,
|
|
500
|
+
dialect: options.dialect.name
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
const createHandle = (tenant, transaction) => {
|
|
505
|
+
const handle = {
|
|
506
|
+
dialect: options.dialect,
|
|
507
|
+
selectFrom(table) {
|
|
508
|
+
return createSelectBuilder(handleAny, options.dialect, table, tenant);
|
|
509
|
+
},
|
|
510
|
+
insertInto(table) {
|
|
511
|
+
return createInsertBuilder(handleAny, options.dialect, table, tenant);
|
|
512
|
+
},
|
|
513
|
+
updateTable(table) {
|
|
514
|
+
return createUpdateBuilder(handleAny, options.dialect, table, tenant);
|
|
515
|
+
},
|
|
516
|
+
deleteFrom(table) {
|
|
517
|
+
return createDeleteBuilder(handleAny, options.dialect, table, tenant);
|
|
518
|
+
},
|
|
519
|
+
raw(query) {
|
|
520
|
+
if (tenant !== undefined && !tenant.allowRaw) {
|
|
521
|
+
throw new TenantError("Raw SQL is disabled on tenant-scoped database handles", {
|
|
522
|
+
tenantId: tenant.id
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
return new ExecutableQuery(handleAny, () => compileRaw(options.dialect, query));
|
|
526
|
+
},
|
|
527
|
+
async execute(query) {
|
|
528
|
+
return executeQuery(query);
|
|
529
|
+
},
|
|
530
|
+
async uow(fn, uowOptions = {}) {
|
|
531
|
+
return runUow(fn, uowOptions, transaction, tenant);
|
|
532
|
+
},
|
|
533
|
+
withTenant(tenantId, tenantOptions = {}) {
|
|
534
|
+
return createHandle({
|
|
535
|
+
id: tenantId,
|
|
536
|
+
column: tenantOptions.column ?? tenant?.column ?? "tenant_id",
|
|
537
|
+
allowRaw: tenantOptions.allowRaw ?? tenant?.allowRaw ?? false
|
|
538
|
+
}, transaction);
|
|
539
|
+
},
|
|
540
|
+
async ping() {
|
|
541
|
+
if (options.driver.ping !== undefined) {
|
|
542
|
+
await options.driver.ping();
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
await handle.execute({ sql: "select 1", params: [], kind: "raw", returning: false });
|
|
546
|
+
},
|
|
547
|
+
async shutdown() {
|
|
548
|
+
await options.driver.shutdown?.();
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
const handleAny = handle;
|
|
552
|
+
if (transaction !== undefined) {
|
|
553
|
+
Object.defineProperty(handle, "outbox", {
|
|
554
|
+
enumerable: true,
|
|
555
|
+
value: {
|
|
556
|
+
publish(type, payload, outboxOptions = {}) {
|
|
557
|
+
return publishOutbox(handle, options, {
|
|
558
|
+
type,
|
|
559
|
+
payload,
|
|
560
|
+
metadata: outboxOptions.metadata ?? {},
|
|
561
|
+
occurredAt: outboxOptions.occurredAt ?? new Date
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
return Object.freeze(handle);
|
|
568
|
+
};
|
|
569
|
+
const runUow = async (fn, uowOptions, existingTransaction, tenant) => {
|
|
570
|
+
if (existingTransaction !== undefined) {
|
|
571
|
+
return runNestedUow(fn, uowOptions, existingTransaction, tenant);
|
|
572
|
+
}
|
|
573
|
+
const attempts = Math.max(0, uowOptions.retries ?? 0) + 1;
|
|
574
|
+
for (let attempt = 1;attempt <= attempts; attempt += 1) {
|
|
575
|
+
const transaction = { savepoint: 0 };
|
|
576
|
+
await executeControl(beginSql(uowOptions));
|
|
577
|
+
const tx = createHandle(tenant, transaction);
|
|
578
|
+
try {
|
|
579
|
+
const result = await fn(tx);
|
|
580
|
+
await executeControl("commit");
|
|
581
|
+
return result;
|
|
582
|
+
} catch (cause) {
|
|
583
|
+
await rollbackQuietly();
|
|
584
|
+
if (attempt < attempts && await shouldRetry(cause, attempt, uowOptions)) {
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
throw cause;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
throw new TransactionError("Transaction retry attempts were exhausted");
|
|
591
|
+
};
|
|
592
|
+
const runNestedUow = async (fn, uowOptions, transaction, tenant) => {
|
|
593
|
+
const attempts = Math.max(0, uowOptions.retries ?? 0) + 1;
|
|
594
|
+
for (let attempt = 1;attempt <= attempts; attempt += 1) {
|
|
595
|
+
const savepoint = `forge_sp_${++transaction.savepoint}`;
|
|
596
|
+
await executeControl(`savepoint ${savepoint}`);
|
|
597
|
+
const tx = createHandle(tenant, transaction);
|
|
598
|
+
try {
|
|
599
|
+
const result = await fn(tx);
|
|
600
|
+
await executeControl(`release savepoint ${savepoint}`);
|
|
601
|
+
return result;
|
|
602
|
+
} catch (cause) {
|
|
603
|
+
await rollbackToSavepointQuietly(savepoint);
|
|
604
|
+
if (attempt < attempts && await shouldRetry(cause, attempt, uowOptions)) {
|
|
605
|
+
continue;
|
|
606
|
+
}
|
|
607
|
+
throw cause;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
throw new TransactionError("Nested transaction retry attempts were exhausted");
|
|
611
|
+
};
|
|
612
|
+
const executeControl = (statement) => executeQuery({ sql: statement, params: [], kind: "raw", returning: false });
|
|
613
|
+
const rollbackQuietly = async () => {
|
|
614
|
+
try {
|
|
615
|
+
await executeControl("rollback");
|
|
616
|
+
} catch {}
|
|
617
|
+
};
|
|
618
|
+
const rollbackToSavepointQuietly = async (savepoint) => {
|
|
619
|
+
try {
|
|
620
|
+
await executeControl(`rollback to savepoint ${savepoint}`);
|
|
621
|
+
} catch {}
|
|
622
|
+
};
|
|
623
|
+
return createHandle();
|
|
624
|
+
}
|
|
625
|
+
var VALID_ISOLATION_LEVELS = new Set([
|
|
626
|
+
"read committed",
|
|
627
|
+
"repeatable read",
|
|
628
|
+
"serializable"
|
|
629
|
+
]);
|
|
630
|
+
function beginSql(options) {
|
|
631
|
+
if (options.isolationLevel === undefined)
|
|
632
|
+
return "begin";
|
|
633
|
+
if (!VALID_ISOLATION_LEVELS.has(options.isolationLevel)) {
|
|
634
|
+
throw new TransactionError(`Invalid isolation level: "${options.isolationLevel}"`);
|
|
635
|
+
}
|
|
636
|
+
return `begin isolation level ${options.isolationLevel}`;
|
|
637
|
+
}
|
|
638
|
+
async function shouldRetry(cause, attempt, options) {
|
|
639
|
+
if (options.shouldRetry === undefined)
|
|
640
|
+
return false;
|
|
641
|
+
return options.shouldRetry(cause, attempt);
|
|
642
|
+
}
|
|
643
|
+
var VALID_TABLE_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
644
|
+
async function publishOutbox(tx, options, message) {
|
|
645
|
+
const normalized = {
|
|
646
|
+
type: message.type,
|
|
647
|
+
payload: message.payload,
|
|
648
|
+
metadata: message.metadata,
|
|
649
|
+
occurredAt: message.occurredAt
|
|
650
|
+
};
|
|
651
|
+
if (options.outbox?.publisher !== undefined) {
|
|
652
|
+
await options.outbox.publisher.publish(normalized, tx);
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
const table = options.outbox?.table ?? "_forge_outbox";
|
|
656
|
+
if (!VALID_TABLE_NAME_RE.test(table)) {
|
|
657
|
+
throw new QueryError(`Invalid outbox table name: "${table}"`, {
|
|
658
|
+
sql: "",
|
|
659
|
+
params: [],
|
|
660
|
+
dialect: options.dialect.name
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
const quote = (identifier) => raw(options.dialect.quoteIdentifier(identifier));
|
|
664
|
+
await tx.execute(compileRaw(options.dialect, sql`
|
|
665
|
+
insert into ${quote(table)}
|
|
666
|
+
(${quote("type")}, ${quote("payload")}, ${quote("metadata")}, ${quote("occurred_at")})
|
|
667
|
+
values (
|
|
668
|
+
${message.type},
|
|
669
|
+
${JSON.stringify(message.payload)},
|
|
670
|
+
${JSON.stringify(message.metadata)},
|
|
671
|
+
${message.occurredAt.toISOString()}
|
|
672
|
+
)
|
|
673
|
+
`));
|
|
674
|
+
}
|
|
675
|
+
function normalizeResult(query, result) {
|
|
676
|
+
if (result.rows.length > 0)
|
|
677
|
+
return result;
|
|
678
|
+
if (query.returning)
|
|
679
|
+
return result;
|
|
680
|
+
if (query.kind === "update") {
|
|
681
|
+
return {
|
|
682
|
+
rows: [{ numUpdatedRows: result.numAffectedRows }],
|
|
683
|
+
numAffectedRows: result.numAffectedRows
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
if (query.kind === "delete") {
|
|
687
|
+
return {
|
|
688
|
+
rows: [{ numDeletedRows: result.numAffectedRows }],
|
|
689
|
+
numAffectedRows: result.numAffectedRows
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
return result;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
// node_modules/@infinityi/forge/dist/data/dialects/postgres/index.js
|
|
696
|
+
function createPostgresDialect() {
|
|
697
|
+
return {
|
|
698
|
+
name: "postgresql",
|
|
699
|
+
placeholder(index) {
|
|
700
|
+
return `$${index}`;
|
|
701
|
+
},
|
|
702
|
+
quoteIdentifier(identifier) {
|
|
703
|
+
return `"${identifier.replaceAll('"', '""')}"`;
|
|
704
|
+
}
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
function createPostgresDriver(options) {
|
|
708
|
+
return {
|
|
709
|
+
name: "postgresql",
|
|
710
|
+
async execute(query) {
|
|
711
|
+
try {
|
|
712
|
+
const result = await options.client.query(query.sql, query.params);
|
|
713
|
+
return {
|
|
714
|
+
rows: result.rows ?? [],
|
|
715
|
+
numAffectedRows: BigInt(result.rowCount ?? result.rows?.length ?? 0)
|
|
716
|
+
};
|
|
717
|
+
} catch (cause) {
|
|
718
|
+
throw new QueryError("PostgreSQL query failed", {
|
|
719
|
+
cause,
|
|
720
|
+
sql: query.sql,
|
|
721
|
+
params: query.params,
|
|
722
|
+
dialect: "postgresql"
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
},
|
|
726
|
+
async ping() {
|
|
727
|
+
await options.client.query("select 1", []);
|
|
728
|
+
},
|
|
729
|
+
async shutdown() {
|
|
730
|
+
if (options.closeOnShutdown === false)
|
|
731
|
+
return;
|
|
732
|
+
await options.client.end?.();
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// node_modules/@infinityi/forge/dist/data/dialects/sqlite/index.js
|
|
738
|
+
import { Database } from "bun:sqlite";
|
|
739
|
+
function createSqliteDialect() {
|
|
740
|
+
return {
|
|
741
|
+
name: "sqlite",
|
|
742
|
+
placeholder() {
|
|
743
|
+
return "?";
|
|
744
|
+
},
|
|
745
|
+
quoteIdentifier(identifier) {
|
|
746
|
+
return `"${identifier.replaceAll('"', '""')}"`;
|
|
747
|
+
}
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
function createSqliteDriver(options = {}) {
|
|
751
|
+
const database = options.database ?? new Database(options.filename ?? ":memory:", {
|
|
752
|
+
create: options.create ?? true
|
|
753
|
+
});
|
|
754
|
+
return {
|
|
755
|
+
name: "sqlite",
|
|
756
|
+
execute(query) {
|
|
757
|
+
try {
|
|
758
|
+
const statement = database.query(query.sql);
|
|
759
|
+
if (query.kind === "select" || rawReturnsRows(query.sql)) {
|
|
760
|
+
const rows = statement.all(...toSqliteBindings(query.params));
|
|
761
|
+
return { rows, numAffectedRows: 0n };
|
|
762
|
+
}
|
|
763
|
+
if (returnsRows(query.sql)) {
|
|
764
|
+
const rows = statement.all(...toSqliteBindings(query.params));
|
|
765
|
+
return { rows, numAffectedRows: BigInt(rows.length) };
|
|
766
|
+
}
|
|
767
|
+
const result = statement.run(...toSqliteBindings(query.params));
|
|
768
|
+
return { rows: [], numAffectedRows: BigInt(result.changes ?? 0) };
|
|
769
|
+
} catch (cause) {
|
|
770
|
+
throw new QueryError("SQLite query failed", {
|
|
771
|
+
cause,
|
|
772
|
+
sql: query.sql,
|
|
773
|
+
params: query.params,
|
|
774
|
+
dialect: "sqlite"
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
},
|
|
778
|
+
shutdown() {
|
|
779
|
+
database.close();
|
|
780
|
+
}
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
function toSqliteBindings(params) {
|
|
784
|
+
return [...params];
|
|
785
|
+
}
|
|
786
|
+
function returnsRows(sql2) {
|
|
787
|
+
return /\breturning\b/i.test(sql2);
|
|
788
|
+
}
|
|
789
|
+
function rawReturnsRows(sql2) {
|
|
790
|
+
return /^\s*(select|with|pragma)\b/i.test(sql2);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// src/session-stores/ids.ts
|
|
794
|
+
import { createHash } from "node:crypto";
|
|
795
|
+
var VALID_TABLE_PREFIX_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
796
|
+
function assertTablePrefix(prefix) {
|
|
797
|
+
if (!VALID_TABLE_PREFIX_RE.test(prefix)) {
|
|
798
|
+
throw new Error(`Invalid session store table prefix: ${JSON.stringify(prefix)}`);
|
|
799
|
+
}
|
|
800
|
+
return prefix;
|
|
801
|
+
}
|
|
802
|
+
function safeSessionKey(id) {
|
|
803
|
+
return Buffer.from(id, "utf8").toString("base64url");
|
|
804
|
+
}
|
|
805
|
+
function sessionFileName(id) {
|
|
806
|
+
return `${createHash("sha256").update(id).digest("hex")}.jsonl`;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// src/session-stores/versioning.ts
|
|
810
|
+
var SESSION_STORE_SCHEMA_VERSION = 1;
|
|
811
|
+
function isVersionedSessionStore(store) {
|
|
812
|
+
return typeof store.migrate === "function";
|
|
813
|
+
}
|
|
814
|
+
function isCloseableSessionStore(store) {
|
|
815
|
+
return typeof store.close === "function";
|
|
816
|
+
}
|
|
817
|
+
async function migrateSessionStore(store) {
|
|
818
|
+
if (isVersionedSessionStore(store))
|
|
819
|
+
await store.migrate();
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// src/session-stores/forge-data.ts
|
|
823
|
+
var DEFAULT_TABLE_PREFIX = "engine_session";
|
|
824
|
+
function table(db, name) {
|
|
825
|
+
return raw(db.dialect.quoteIdentifier(name));
|
|
826
|
+
}
|
|
827
|
+
function tablesFor(db, prefix) {
|
|
828
|
+
const valid = assertTablePrefix(prefix);
|
|
829
|
+
return {
|
|
830
|
+
sessions: table(db, `${valid}_sessions`),
|
|
831
|
+
messages: table(db, `${valid}_messages`),
|
|
832
|
+
meta: table(db, `${valid}_meta`)
|
|
833
|
+
};
|
|
834
|
+
}
|
|
835
|
+
function toNumber(value) {
|
|
836
|
+
if (typeof value === "number")
|
|
837
|
+
return value;
|
|
838
|
+
if (typeof value === "bigint")
|
|
839
|
+
return Number(value);
|
|
840
|
+
return Number.parseInt(value, 10);
|
|
841
|
+
}
|
|
842
|
+
function stateOf(id, messages, metadata) {
|
|
843
|
+
return {
|
|
844
|
+
id,
|
|
845
|
+
messages: [...messages],
|
|
846
|
+
...metadata !== undefined ? { metadata: { ...metadata } } : {}
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
class ForgeDataSessionStore {
|
|
851
|
+
db;
|
|
852
|
+
codec;
|
|
853
|
+
tables;
|
|
854
|
+
closeDbOnClose;
|
|
855
|
+
writeQueue = Promise.resolve();
|
|
856
|
+
constructor(options) {
|
|
857
|
+
this.db = options.db;
|
|
858
|
+
this.codec = options.codec ?? jsonSessionStoreCodec;
|
|
859
|
+
this.tables = tablesFor(options.db, options.tablePrefix ?? DEFAULT_TABLE_PREFIX);
|
|
860
|
+
this.closeDbOnClose = options.closeDbOnClose ?? false;
|
|
861
|
+
}
|
|
862
|
+
async migrate() {
|
|
863
|
+
await this.db.raw(sql`
|
|
864
|
+
create table if not exists ${this.tables.sessions} (
|
|
865
|
+
id text primary key,
|
|
866
|
+
metadata text null,
|
|
867
|
+
next_seq integer not null default 0,
|
|
868
|
+
created_at text not null,
|
|
869
|
+
updated_at text not null
|
|
870
|
+
)
|
|
871
|
+
`).execute();
|
|
872
|
+
await this.db.raw(sql`
|
|
873
|
+
create table if not exists ${this.tables.messages} (
|
|
874
|
+
session_id text not null,
|
|
875
|
+
seq integer not null,
|
|
876
|
+
payload text not null,
|
|
877
|
+
created_at text not null,
|
|
878
|
+
primary key (session_id, seq)
|
|
879
|
+
)
|
|
880
|
+
`).execute();
|
|
881
|
+
await this.db.raw(sql`
|
|
882
|
+
create table if not exists ${this.tables.meta} (
|
|
883
|
+
key text primary key,
|
|
884
|
+
value text not null
|
|
885
|
+
)
|
|
886
|
+
`).execute();
|
|
887
|
+
await this.db.raw(sql`
|
|
888
|
+
insert into ${this.tables.meta} (key, value)
|
|
889
|
+
values (${"schema_version"}, ${String(SESSION_STORE_SCHEMA_VERSION)})
|
|
890
|
+
on conflict (key) do update set value = excluded.value
|
|
891
|
+
`).execute();
|
|
892
|
+
}
|
|
893
|
+
async schemaVersion() {
|
|
894
|
+
const row = await this.db.raw(sql`
|
|
895
|
+
select value from ${this.tables.meta} where key = ${"schema_version"}
|
|
896
|
+
`).executeTakeFirst();
|
|
897
|
+
return row === undefined ? undefined : Number.parseInt(row.value, 10);
|
|
898
|
+
}
|
|
899
|
+
async load(id) {
|
|
900
|
+
await this.writeQueue.catch(() => {});
|
|
901
|
+
const session = await this.db.raw(sql`
|
|
902
|
+
select id, metadata from ${this.tables.sessions} where id = ${id}
|
|
903
|
+
`).executeTakeFirst();
|
|
904
|
+
if (session === undefined)
|
|
905
|
+
return;
|
|
906
|
+
const rows = await this.db.raw(sql`
|
|
907
|
+
select payload from ${this.tables.messages}
|
|
908
|
+
where session_id = ${id}
|
|
909
|
+
order by seq asc
|
|
910
|
+
`).execute();
|
|
911
|
+
const messages = await decodeMessages(this.codec, rows.rows.map((row) => row.payload));
|
|
912
|
+
const metadata = await decodeMetadata(this.codec, session.metadata);
|
|
913
|
+
return stateOf(id, messages, metadata);
|
|
914
|
+
}
|
|
915
|
+
async append(id, messages) {
|
|
916
|
+
if (messages.length === 0)
|
|
917
|
+
return;
|
|
918
|
+
const encoded = await encodeMessages(this.codec, messages);
|
|
919
|
+
const now = new Date().toISOString();
|
|
920
|
+
await this.enqueueWrite(async () => this.db.uow(async (tx) => {
|
|
921
|
+
await tx.raw(sql`
|
|
922
|
+
insert into ${this.tables.sessions} (id, metadata, next_seq, created_at, updated_at)
|
|
923
|
+
values (${id}, null, 0, ${now}, ${now})
|
|
924
|
+
on conflict (id) do nothing
|
|
925
|
+
`).execute();
|
|
926
|
+
const row = await tx.raw(sql`
|
|
927
|
+
update ${this.tables.sessions}
|
|
928
|
+
set next_seq = next_seq + ${encoded.length}, updated_at = ${now}
|
|
929
|
+
where id = ${id}
|
|
930
|
+
returning next_seq
|
|
931
|
+
`).executeTakeFirst();
|
|
932
|
+
if (row === undefined)
|
|
933
|
+
throw new Error(`Failed to allocate session sequence for ${id}`);
|
|
934
|
+
const start = toNumber(row.next_seq) - encoded.length;
|
|
935
|
+
for (let index = 0;index < encoded.length; index += 1) {
|
|
936
|
+
await tx.raw(sql`
|
|
937
|
+
insert into ${this.tables.messages} (session_id, seq, payload, created_at)
|
|
938
|
+
values (${id}, ${start + index}, ${encoded[index]}, ${now})
|
|
939
|
+
`).execute();
|
|
940
|
+
}
|
|
941
|
+
}));
|
|
942
|
+
}
|
|
943
|
+
async save(state) {
|
|
944
|
+
const encoded = await encodeMessages(this.codec, state.messages);
|
|
945
|
+
const metadata = await encodeMetadata(this.codec, state.metadata);
|
|
946
|
+
const now = new Date().toISOString();
|
|
947
|
+
await this.enqueueWrite(async () => this.db.uow(async (tx) => {
|
|
948
|
+
await tx.raw(sql`
|
|
949
|
+
insert into ${this.tables.sessions} (id, metadata, next_seq, created_at, updated_at)
|
|
950
|
+
values (${state.id}, ${metadata ?? null}, ${encoded.length}, ${now}, ${now})
|
|
951
|
+
on conflict (id) do update set
|
|
952
|
+
metadata = excluded.metadata,
|
|
953
|
+
next_seq = excluded.next_seq,
|
|
954
|
+
updated_at = excluded.updated_at
|
|
955
|
+
`).execute();
|
|
956
|
+
await tx.raw(sql`
|
|
957
|
+
delete from ${this.tables.messages} where session_id = ${state.id}
|
|
958
|
+
`).execute();
|
|
959
|
+
for (let index = 0;index < encoded.length; index += 1) {
|
|
960
|
+
await tx.raw(sql`
|
|
961
|
+
insert into ${this.tables.messages} (session_id, seq, payload, created_at)
|
|
962
|
+
values (${state.id}, ${index}, ${encoded[index]}, ${now})
|
|
963
|
+
`).execute();
|
|
964
|
+
}
|
|
965
|
+
}));
|
|
966
|
+
}
|
|
967
|
+
async delete(id) {
|
|
968
|
+
await this.enqueueWrite(async () => this.db.uow(async (tx) => {
|
|
969
|
+
await tx.raw(sql`delete from ${this.tables.messages} where session_id = ${id}`).execute();
|
|
970
|
+
await tx.raw(sql`delete from ${this.tables.sessions} where id = ${id}`).execute();
|
|
971
|
+
}));
|
|
972
|
+
}
|
|
973
|
+
async close() {
|
|
974
|
+
await this.writeQueue.catch(() => {});
|
|
975
|
+
if (this.closeDbOnClose)
|
|
976
|
+
await this.db.shutdown();
|
|
977
|
+
}
|
|
978
|
+
enqueueWrite(task) {
|
|
979
|
+
const run = this.writeQueue.catch(() => {}).then(task);
|
|
980
|
+
this.writeQueue = run.then(() => {
|
|
981
|
+
return;
|
|
982
|
+
}, () => {
|
|
983
|
+
return;
|
|
984
|
+
});
|
|
985
|
+
return run;
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
async function createSqliteSessionStore(options = {}) {
|
|
989
|
+
const db = createDb({
|
|
990
|
+
dialect: createSqliteDialect(),
|
|
991
|
+
driver: createSqliteDriver({
|
|
992
|
+
database: options.database,
|
|
993
|
+
filename: options.filename,
|
|
994
|
+
create: options.create
|
|
995
|
+
})
|
|
996
|
+
});
|
|
997
|
+
const store = new ForgeDataSessionStore({
|
|
998
|
+
db,
|
|
999
|
+
tablePrefix: options.tablePrefix,
|
|
1000
|
+
codec: options.codec,
|
|
1001
|
+
closeDbOnClose: true
|
|
1002
|
+
});
|
|
1003
|
+
if (options.migrate)
|
|
1004
|
+
await store.migrate();
|
|
1005
|
+
return store;
|
|
1006
|
+
}
|
|
1007
|
+
async function createPostgresSessionStore(options) {
|
|
1008
|
+
const db = createDb({
|
|
1009
|
+
dialect: createPostgresDialect(),
|
|
1010
|
+
driver: createPostgresDriver({
|
|
1011
|
+
client: options.client,
|
|
1012
|
+
closeOnShutdown: options.closeOnShutdown
|
|
1013
|
+
})
|
|
1014
|
+
});
|
|
1015
|
+
const store = new ForgeDataSessionStore({
|
|
1016
|
+
db,
|
|
1017
|
+
tablePrefix: options.tablePrefix,
|
|
1018
|
+
codec: options.codec,
|
|
1019
|
+
closeDbOnClose: true
|
|
1020
|
+
});
|
|
1021
|
+
if (options.migrate)
|
|
1022
|
+
await store.migrate();
|
|
1023
|
+
return store;
|
|
1024
|
+
}
|
|
1025
|
+
// src/session-stores/hooks.ts
|
|
1026
|
+
function snapshot(state) {
|
|
1027
|
+
return {
|
|
1028
|
+
id: state.id,
|
|
1029
|
+
messages: [...state.messages],
|
|
1030
|
+
...state.metadata !== undefined ? { metadata: { ...state.metadata } } : {}
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
function isCompactionResult(value) {
|
|
1034
|
+
return typeof value === "object" && value !== null && "state" in value;
|
|
1035
|
+
}
|
|
1036
|
+
function withSessionStoreHooks(store, hooks) {
|
|
1037
|
+
let runningHooks = false;
|
|
1038
|
+
async function runHooks(operation, id) {
|
|
1039
|
+
if (runningHooks || hooks.compactor === undefined)
|
|
1040
|
+
return;
|
|
1041
|
+
const current = await store.load(id);
|
|
1042
|
+
if (current === undefined)
|
|
1043
|
+
return;
|
|
1044
|
+
const context = { operation, store: wrapped };
|
|
1045
|
+
const shouldCompact = hooks.compactor.shouldCompact === undefined ? true : await hooks.compactor.shouldCompact(snapshot(current), context);
|
|
1046
|
+
if (!shouldCompact)
|
|
1047
|
+
return;
|
|
1048
|
+
runningHooks = true;
|
|
1049
|
+
try {
|
|
1050
|
+
const result = await hooks.compactor.compact(snapshot(current), context);
|
|
1051
|
+
const replacement = isCompactionResult(result) ? result.state : result;
|
|
1052
|
+
if (isCompactionResult(result) && result.archive !== undefined && hooks.archiver !== undefined) {
|
|
1053
|
+
await hooks.archiver.archive({
|
|
1054
|
+
id,
|
|
1055
|
+
at: new Date().toISOString(),
|
|
1056
|
+
operation,
|
|
1057
|
+
...result.archive
|
|
1058
|
+
}, context);
|
|
1059
|
+
}
|
|
1060
|
+
await store.save(snapshot(replacement));
|
|
1061
|
+
} finally {
|
|
1062
|
+
runningHooks = false;
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
const wrapped = {
|
|
1066
|
+
load(id) {
|
|
1067
|
+
return store.load(id);
|
|
1068
|
+
},
|
|
1069
|
+
async append(id, messages) {
|
|
1070
|
+
await store.append(id, messages);
|
|
1071
|
+
if (messages.length > 0)
|
|
1072
|
+
await runHooks("append", id);
|
|
1073
|
+
},
|
|
1074
|
+
async save(state) {
|
|
1075
|
+
await store.save(state);
|
|
1076
|
+
await runHooks("save", state.id);
|
|
1077
|
+
},
|
|
1078
|
+
delete(id) {
|
|
1079
|
+
return store.delete(id);
|
|
1080
|
+
}
|
|
1081
|
+
};
|
|
1082
|
+
if (isVersionedSessionStore(store)) {
|
|
1083
|
+
wrapped.migrate = () => store.migrate();
|
|
1084
|
+
}
|
|
1085
|
+
if (isCloseableSessionStore(store)) {
|
|
1086
|
+
wrapped.close = () => store.close();
|
|
1087
|
+
}
|
|
1088
|
+
return wrapped;
|
|
1089
|
+
}
|
|
1090
|
+
// src/session-stores/jsonl.ts
|
|
1091
|
+
import { appendFile, mkdir, readdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
1092
|
+
import { join } from "node:path";
|
|
1093
|
+
function isMissingFile(error) {
|
|
1094
|
+
return typeof error === "object" && error !== null && error.code === "ENOENT";
|
|
1095
|
+
}
|
|
1096
|
+
function buildState(id, messages, metadata) {
|
|
1097
|
+
return {
|
|
1098
|
+
id,
|
|
1099
|
+
messages: [...messages],
|
|
1100
|
+
...metadata !== undefined ? { metadata: { ...metadata } } : {}
|
|
1101
|
+
};
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
class FilesystemJsonlSessionStore {
|
|
1105
|
+
directory;
|
|
1106
|
+
codec;
|
|
1107
|
+
queues = new Map;
|
|
1108
|
+
constructor(options) {
|
|
1109
|
+
this.directory = options.directory;
|
|
1110
|
+
this.codec = options.codec ?? jsonSessionStoreCodec;
|
|
1111
|
+
}
|
|
1112
|
+
async migrate() {
|
|
1113
|
+
await mkdir(this.directory, { recursive: true });
|
|
1114
|
+
await writeFile(join(this.directory, ".engine-session-store-version"), `${SESSION_STORE_SCHEMA_VERSION}
|
|
1115
|
+
`, "utf8");
|
|
1116
|
+
}
|
|
1117
|
+
async load(id) {
|
|
1118
|
+
await this.waitForWrites(id);
|
|
1119
|
+
return (await this.replayFile(this.pathFor(id), id)).state;
|
|
1120
|
+
}
|
|
1121
|
+
async append(id, messages) {
|
|
1122
|
+
if (messages.length === 0)
|
|
1123
|
+
return;
|
|
1124
|
+
await this.enqueue(id, async () => {
|
|
1125
|
+
const record = {
|
|
1126
|
+
version: SESSION_STORE_SCHEMA_VERSION,
|
|
1127
|
+
op: "append",
|
|
1128
|
+
id,
|
|
1129
|
+
at: new Date().toISOString(),
|
|
1130
|
+
messages: await encodeMessages(this.codec, messages)
|
|
1131
|
+
};
|
|
1132
|
+
await this.appendRecord(id, record);
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
async save(state) {
|
|
1136
|
+
await this.enqueue(state.id, async () => {
|
|
1137
|
+
const metadata = await encodeMetadata(this.codec, state.metadata);
|
|
1138
|
+
const record = {
|
|
1139
|
+
version: SESSION_STORE_SCHEMA_VERSION,
|
|
1140
|
+
op: "save",
|
|
1141
|
+
id: state.id,
|
|
1142
|
+
at: new Date().toISOString(),
|
|
1143
|
+
messages: await encodeMessages(this.codec, state.messages),
|
|
1144
|
+
...metadata !== undefined ? { metadata } : {}
|
|
1145
|
+
};
|
|
1146
|
+
await this.appendRecord(state.id, record);
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
1149
|
+
async delete(id) {
|
|
1150
|
+
await this.enqueue(id, async () => {
|
|
1151
|
+
await this.appendRecord(id, {
|
|
1152
|
+
version: SESSION_STORE_SCHEMA_VERSION,
|
|
1153
|
+
op: "delete",
|
|
1154
|
+
id,
|
|
1155
|
+
at: new Date().toISOString()
|
|
1156
|
+
});
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
async compact(id) {
|
|
1160
|
+
if (id !== undefined) {
|
|
1161
|
+
await this.enqueue(id, () => this.compactFile(this.pathFor(id), id));
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1164
|
+
await this.migrate();
|
|
1165
|
+
const entries = await readdir(this.directory, { withFileTypes: true });
|
|
1166
|
+
for (const entry of entries) {
|
|
1167
|
+
if (!entry.isFile() || !entry.name.endsWith(".jsonl"))
|
|
1168
|
+
continue;
|
|
1169
|
+
await this.compactFile(join(this.directory, entry.name));
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
pathFor(id) {
|
|
1173
|
+
return join(this.directory, sessionFileName(id));
|
|
1174
|
+
}
|
|
1175
|
+
async waitForWrites(id) {
|
|
1176
|
+
await (this.queues.get(id) ?? Promise.resolve()).catch(() => {});
|
|
1177
|
+
}
|
|
1178
|
+
async enqueue(id, task) {
|
|
1179
|
+
const previous = this.queues.get(id) ?? Promise.resolve();
|
|
1180
|
+
const run = previous.catch(() => {}).then(task);
|
|
1181
|
+
const next = run.then(() => {
|
|
1182
|
+
return;
|
|
1183
|
+
}, () => {
|
|
1184
|
+
return;
|
|
1185
|
+
});
|
|
1186
|
+
this.queues.set(id, next);
|
|
1187
|
+
try {
|
|
1188
|
+
return await run;
|
|
1189
|
+
} finally {
|
|
1190
|
+
if (this.queues.get(id) === next)
|
|
1191
|
+
this.queues.delete(id);
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
async appendRecord(id, record) {
|
|
1195
|
+
await mkdir(this.directory, { recursive: true });
|
|
1196
|
+
await appendFile(this.pathFor(id), `${JSON.stringify(record)}
|
|
1197
|
+
`, "utf8");
|
|
1198
|
+
}
|
|
1199
|
+
async replayFile(path, expectedId) {
|
|
1200
|
+
let text;
|
|
1201
|
+
try {
|
|
1202
|
+
text = await readFile(path, "utf8");
|
|
1203
|
+
} catch (error) {
|
|
1204
|
+
if (isMissingFile(error))
|
|
1205
|
+
return { id: expectedId, state: undefined };
|
|
1206
|
+
throw error;
|
|
1207
|
+
}
|
|
1208
|
+
let id = expectedId;
|
|
1209
|
+
let messages = [];
|
|
1210
|
+
let metadata;
|
|
1211
|
+
let exists = false;
|
|
1212
|
+
for (const rawLine of text.split(/\r?\n/)) {
|
|
1213
|
+
const line = rawLine.trim();
|
|
1214
|
+
if (line.length === 0)
|
|
1215
|
+
continue;
|
|
1216
|
+
const record = JSON.parse(line);
|
|
1217
|
+
if (id === undefined)
|
|
1218
|
+
id = record.id;
|
|
1219
|
+
if (record.id !== id)
|
|
1220
|
+
continue;
|
|
1221
|
+
if (record.op === "delete") {
|
|
1222
|
+
exists = false;
|
|
1223
|
+
messages = [];
|
|
1224
|
+
metadata = undefined;
|
|
1225
|
+
} else if (record.op === "save") {
|
|
1226
|
+
exists = true;
|
|
1227
|
+
messages = await decodeMessages(this.codec, record.messages);
|
|
1228
|
+
metadata = await decodeMetadata(this.codec, record.metadata);
|
|
1229
|
+
} else {
|
|
1230
|
+
exists = true;
|
|
1231
|
+
messages.push(...await decodeMessages(this.codec, record.messages));
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
if (!exists || id === undefined)
|
|
1235
|
+
return { id, state: undefined };
|
|
1236
|
+
return { id, state: buildState(id, messages, metadata) };
|
|
1237
|
+
}
|
|
1238
|
+
async compactFile(path, expectedId) {
|
|
1239
|
+
const replayed = await this.replayFile(path, expectedId);
|
|
1240
|
+
if (replayed.id === undefined)
|
|
1241
|
+
return;
|
|
1242
|
+
if (replayed.state === undefined) {
|
|
1243
|
+
await rm(path, { force: true });
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1246
|
+
const metadata = await encodeMetadata(this.codec, replayed.state.metadata);
|
|
1247
|
+
const record = {
|
|
1248
|
+
version: SESSION_STORE_SCHEMA_VERSION,
|
|
1249
|
+
op: "save",
|
|
1250
|
+
id: replayed.id,
|
|
1251
|
+
at: new Date().toISOString(),
|
|
1252
|
+
messages: await encodeMessages(this.codec, replayed.state.messages),
|
|
1253
|
+
...metadata !== undefined ? { metadata } : {}
|
|
1254
|
+
};
|
|
1255
|
+
const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;
|
|
1256
|
+
await writeFile(tmp, `${JSON.stringify(record)}
|
|
1257
|
+
`, "utf8");
|
|
1258
|
+
await rename(tmp, path);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
// src/session-stores/redis.ts
|
|
1262
|
+
function metadataState(id, messages, metadata) {
|
|
1263
|
+
return {
|
|
1264
|
+
id,
|
|
1265
|
+
messages: [...messages],
|
|
1266
|
+
...metadata !== undefined ? { metadata: { ...metadata } } : {}
|
|
1267
|
+
};
|
|
1268
|
+
}
|
|
1269
|
+
function rpushTransaction(tx, key, values) {
|
|
1270
|
+
if (values.length === 0)
|
|
1271
|
+
return;
|
|
1272
|
+
if (tx.rPush !== undefined) {
|
|
1273
|
+
tx.rPush(key, ...values);
|
|
1274
|
+
return;
|
|
1275
|
+
}
|
|
1276
|
+
if (tx.rpush !== undefined) {
|
|
1277
|
+
tx.rpush(key, ...values);
|
|
1278
|
+
return;
|
|
1279
|
+
}
|
|
1280
|
+
throw new Error("Redis session store transaction must implement rPush/rpush");
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
class RedisSessionStore {
|
|
1284
|
+
client;
|
|
1285
|
+
keyPrefix;
|
|
1286
|
+
codec;
|
|
1287
|
+
constructor(options) {
|
|
1288
|
+
this.client = options.client;
|
|
1289
|
+
this.keyPrefix = options.keyPrefix ?? "engine:sessions";
|
|
1290
|
+
this.codec = options.codec ?? jsonSessionStoreCodec;
|
|
1291
|
+
}
|
|
1292
|
+
async migrate() {
|
|
1293
|
+
await this.client.set(this.versionKey(), String(SESSION_STORE_SCHEMA_VERSION));
|
|
1294
|
+
}
|
|
1295
|
+
async load(id) {
|
|
1296
|
+
const payloads = await this.lRange(this.messagesKey(id), 0, -1);
|
|
1297
|
+
const metadataPayload = await this.client.get(this.metadataKey(id));
|
|
1298
|
+
const exists = await this.client.get(this.existsKey(id));
|
|
1299
|
+
if (payloads.length === 0 && metadataPayload == null && exists == null)
|
|
1300
|
+
return;
|
|
1301
|
+
const metadata = await decodeMetadata(this.codec, metadataPayload);
|
|
1302
|
+
const messages = await decodeMessages(this.codec, payloads);
|
|
1303
|
+
return metadataState(id, messages, metadata);
|
|
1304
|
+
}
|
|
1305
|
+
async append(id, messages) {
|
|
1306
|
+
if (messages.length === 0)
|
|
1307
|
+
return;
|
|
1308
|
+
const encoded = await encodeMessages(this.codec, messages);
|
|
1309
|
+
await this.rPush(this.messagesKey(id), encoded);
|
|
1310
|
+
}
|
|
1311
|
+
async save(state) {
|
|
1312
|
+
const tx = this.transaction();
|
|
1313
|
+
const messagesKey = this.messagesKey(state.id);
|
|
1314
|
+
const metadataKey = this.metadataKey(state.id);
|
|
1315
|
+
const existsKey = this.existsKey(state.id);
|
|
1316
|
+
const encoded = await encodeMessages(this.codec, state.messages);
|
|
1317
|
+
const metadata = await encodeMetadata(this.codec, state.metadata);
|
|
1318
|
+
tx.del(messagesKey, metadataKey, existsKey);
|
|
1319
|
+
tx.set(existsKey, "1");
|
|
1320
|
+
if (metadata !== undefined)
|
|
1321
|
+
tx.set(metadataKey, metadata);
|
|
1322
|
+
rpushTransaction(tx, messagesKey, encoded);
|
|
1323
|
+
await tx.exec();
|
|
1324
|
+
}
|
|
1325
|
+
async delete(id) {
|
|
1326
|
+
const tx = this.transaction();
|
|
1327
|
+
tx.del(this.messagesKey(id), this.metadataKey(id), this.existsKey(id));
|
|
1328
|
+
await tx.exec();
|
|
1329
|
+
}
|
|
1330
|
+
transaction() {
|
|
1331
|
+
const tx = this.client.multi?.();
|
|
1332
|
+
if (tx === undefined)
|
|
1333
|
+
throw new Error("Redis session store save/delete require a transaction-capable client");
|
|
1334
|
+
return tx;
|
|
1335
|
+
}
|
|
1336
|
+
async lRange(key, start, stop) {
|
|
1337
|
+
if (this.client.lRange !== undefined)
|
|
1338
|
+
return this.client.lRange(key, start, stop);
|
|
1339
|
+
if (this.client.lrange !== undefined)
|
|
1340
|
+
return this.client.lrange(key, start, stop);
|
|
1341
|
+
throw new Error("Redis session store client must implement lRange/lrange");
|
|
1342
|
+
}
|
|
1343
|
+
async rPush(key, values) {
|
|
1344
|
+
if (this.client.rPush !== undefined) {
|
|
1345
|
+
await this.client.rPush(key, ...values);
|
|
1346
|
+
return;
|
|
1347
|
+
}
|
|
1348
|
+
if (this.client.rpush !== undefined) {
|
|
1349
|
+
await this.client.rpush(key, ...values);
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1352
|
+
throw new Error("Redis session store client must implement rPush/rpush");
|
|
1353
|
+
}
|
|
1354
|
+
idKey(id) {
|
|
1355
|
+
return `${this.keyPrefix}:${safeSessionKey(id)}`;
|
|
1356
|
+
}
|
|
1357
|
+
messagesKey(id) {
|
|
1358
|
+
return `${this.idKey(id)}:messages`;
|
|
1359
|
+
}
|
|
1360
|
+
metadataKey(id) {
|
|
1361
|
+
return `${this.idKey(id)}:metadata`;
|
|
1362
|
+
}
|
|
1363
|
+
existsKey(id) {
|
|
1364
|
+
return `${this.idKey(id)}:exists`;
|
|
1365
|
+
}
|
|
1366
|
+
versionKey() {
|
|
1367
|
+
return `${this.keyPrefix}:meta:version`;
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
export {
|
|
1371
|
+
withSessionStoreHooks,
|
|
1372
|
+
migrateSessionStore,
|
|
1373
|
+
jsonSessionStoreCodec,
|
|
1374
|
+
isVersionedSessionStore,
|
|
1375
|
+
isCloseableSessionStore,
|
|
1376
|
+
createSqliteSessionStore,
|
|
1377
|
+
createPostgresSessionStore,
|
|
1378
|
+
SESSION_STORE_SCHEMA_VERSION,
|
|
1379
|
+
RedisSessionStore,
|
|
1380
|
+
ForgeDataSessionStore,
|
|
1381
|
+
FilesystemJsonlSessionStore
|
|
1382
|
+
};
|