@frontmcp/sdk 0.5.1 → 0.6.1
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 +1 -0
- package/package.json +12 -16
- package/src/adapter/adapter.instance.js +5 -0
- package/src/adapter/adapter.instance.js.map +1 -1
- package/src/auth/authorization/authorization.class.d.ts +1 -4
- package/src/auth/authorization/authorization.class.js +6 -13
- package/src/auth/authorization/authorization.class.js.map +1 -1
- package/src/auth/flows/session.verify.flow.d.ts +1 -0
- package/src/auth/flows/session.verify.flow.js +11 -1
- package/src/auth/flows/session.verify.flow.js.map +1 -1
- package/src/auth/flows/well-known.jwks.flow.js +2 -2
- package/src/auth/flows/well-known.jwks.flow.js.map +1 -1
- package/src/auth/jwks/dev-key-persistence.d.ts +63 -0
- package/src/auth/jwks/dev-key-persistence.js +219 -0
- package/src/auth/jwks/dev-key-persistence.js.map +1 -0
- package/src/auth/jwks/index.d.ts +1 -0
- package/src/auth/jwks/index.js +1 -0
- package/src/auth/jwks/index.js.map +1 -1
- package/src/auth/jwks/jwks.service.d.ts +7 -4
- package/src/auth/jwks/jwks.service.js +81 -12
- package/src/auth/jwks/jwks.service.js.map +1 -1
- package/src/auth/jwks/jwks.types.d.ts +7 -0
- package/src/auth/jwks/jwks.types.js.map +1 -1
- package/src/auth/machine-id.d.ts +5 -0
- package/src/auth/machine-id.js +32 -0
- package/src/auth/machine-id.js.map +1 -0
- package/src/auth/session/index.d.ts +2 -0
- package/src/auth/session/index.js +5 -1
- package/src/auth/session/index.js.map +1 -1
- package/src/auth/session/record/session.base.js +5 -3
- package/src/auth/session/record/session.base.js.map +1 -1
- package/src/auth/session/record/session.stateless.d.ts +2 -2
- package/src/auth/session/record/session.stateless.js +5 -3
- package/src/auth/session/record/session.stateless.js.map +1 -1
- package/src/auth/session/redis-session.store.d.ts +64 -0
- package/src/auth/session/redis-session.store.js +204 -0
- package/src/auth/session/redis-session.store.js.map +1 -0
- package/src/auth/session/session.service.d.ts +0 -2
- package/src/auth/session/session.service.js +1 -7
- package/src/auth/session/session.service.js.map +1 -1
- package/src/auth/session/transport-session.manager.js +3 -5
- package/src/auth/session/transport-session.manager.js.map +1 -1
- package/src/auth/session/transport-session.types.d.ts +4 -0
- package/src/auth/session/transport-session.types.js +4 -3
- package/src/auth/session/transport-session.types.js.map +1 -1
- package/src/auth/session/utils/session-id.utils.d.ts +12 -1
- package/src/auth/session/utils/session-id.utils.js +48 -9
- package/src/auth/session/utils/session-id.utils.js.map +1 -1
- package/src/auth/session/vercel-kv-session.store.d.ts +96 -0
- package/src/auth/session/vercel-kv-session.store.js +216 -0
- package/src/auth/session/vercel-kv-session.store.js.map +1 -0
- package/src/auth/ui/base-layout.d.ts +0 -8
- package/src/auth/ui/base-layout.js +1 -14
- package/src/auth/ui/base-layout.js.map +1 -1
- package/src/auth/ui/index.d.ts +3 -4
- package/src/auth/ui/index.js +10 -11
- package/src/auth/ui/index.js.map +1 -1
- package/src/auth/ui/{htmx-templates.d.ts → templates.d.ts} +5 -6
- package/src/auth/ui/{htmx-templates.js → templates.js} +8 -15
- package/src/auth/ui/templates.js.map +1 -0
- package/src/common/decorators/decorator-utils.js.map +1 -1
- package/src/common/decorators/front-mcp.decorator.js +26 -3
- package/src/common/decorators/front-mcp.decorator.js.map +1 -1
- package/src/common/index.d.ts +0 -1
- package/src/common/index.js +0 -1
- package/src/common/index.js.map +1 -1
- package/src/common/interfaces/adapter.interface.d.ts +6 -0
- package/src/common/interfaces/adapter.interface.js.map +1 -1
- package/src/common/interfaces/execution-context.interface.d.ts +52 -3
- package/src/common/interfaces/execution-context.interface.js +88 -3
- package/src/common/interfaces/execution-context.interface.js.map +1 -1
- package/src/common/interfaces/flow.interface.d.ts +13 -0
- package/src/common/interfaces/flow.interface.js +24 -0
- package/src/common/interfaces/flow.interface.js.map +1 -1
- package/src/common/interfaces/server.interface.d.ts +9 -0
- package/src/common/interfaces/server.interface.js.map +1 -1
- package/src/common/metadata/app.metadata.d.ts +108 -0
- package/src/common/metadata/front-mcp.metadata.d.ts +1341 -2
- package/src/common/metadata/front-mcp.metadata.js +4 -1
- package/src/common/metadata/front-mcp.metadata.js.map +1 -1
- package/src/common/metadata/prompt.metadata.d.ts +4 -0
- package/src/common/metadata/provider.metadata.d.ts +14 -0
- package/src/common/metadata/provider.metadata.js +18 -2
- package/src/common/metadata/provider.metadata.js.map +1 -1
- package/src/common/metadata/resource.metadata.d.ts +8 -0
- package/src/common/metadata/tool-ui.metadata.d.ts +2 -2
- package/src/common/metadata/tool-ui.metadata.js +1 -1
- package/src/common/metadata/tool-ui.metadata.js.map +1 -1
- package/src/common/metadata/tool.metadata.d.ts +5 -1
- package/src/common/metadata/tool.metadata.js.map +1 -1
- package/src/common/migrate/auth-transport.migrate.d.ts +62 -0
- package/src/common/migrate/auth-transport.migrate.js +140 -0
- package/src/common/migrate/auth-transport.migrate.js.map +1 -0
- package/src/common/migrate/index.d.ts +1 -0
- package/src/common/migrate/index.js +6 -0
- package/src/common/migrate/index.js.map +1 -0
- package/src/common/schemas/http-output.schema.d.ts +24 -6
- package/src/common/schemas/index.d.ts +1 -0
- package/src/common/schemas/index.js +1 -0
- package/src/common/schemas/index.js.map +1 -1
- package/src/common/schemas/session-header.schema.d.ts +16 -0
- package/src/common/schemas/session-header.schema.js +42 -0
- package/src/common/schemas/session-header.schema.js.map +1 -0
- package/src/common/tokens/front-mcp.tokens.js +4 -1
- package/src/common/tokens/front-mcp.tokens.js.map +1 -1
- package/src/common/types/options/auth.options.d.ts +233 -3
- package/src/common/types/options/auth.options.js +29 -40
- package/src/common/types/options/auth.options.js.map +1 -1
- package/src/common/types/options/index.d.ts +2 -0
- package/src/common/types/options/index.js +2 -0
- package/src/common/types/options/index.js.map +1 -1
- package/src/common/types/options/redis.options.d.ts +190 -0
- package/src/common/types/options/redis.options.js +191 -0
- package/src/common/types/options/redis.options.js.map +1 -0
- package/src/common/types/options/server-info.options.d.ts +4 -0
- package/src/common/types/options/transport.options.d.ts +148 -0
- package/src/common/types/options/transport.options.js +121 -0
- package/src/common/types/options/transport.options.js.map +1 -0
- package/src/common/utils/global-config.utils.d.ts +36 -0
- package/src/common/utils/global-config.utils.js +44 -0
- package/src/common/utils/global-config.utils.js.map +1 -0
- package/src/common/utils/index.d.ts +1 -0
- package/src/common/utils/index.js +1 -0
- package/src/common/utils/index.js.map +1 -1
- package/src/completion/flows/complete.flow.d.ts +6 -8
- package/src/context/frontmcp-context-storage.d.ts +94 -0
- package/src/context/frontmcp-context-storage.js +183 -0
- package/src/context/frontmcp-context-storage.js.map +1 -0
- package/src/context/frontmcp-context.d.ts +269 -0
- package/src/context/frontmcp-context.js +360 -0
- package/src/context/frontmcp-context.js.map +1 -0
- package/src/context/frontmcp-context.provider.d.ts +43 -0
- package/src/context/frontmcp-context.provider.js +61 -0
- package/src/context/frontmcp-context.provider.js.map +1 -0
- package/src/context/index.d.ts +34 -0
- package/src/context/index.js +64 -0
- package/src/context/index.js.map +1 -0
- package/src/context/request-context-storage.d.ts +89 -0
- package/src/context/request-context-storage.js +183 -0
- package/src/context/request-context-storage.js.map +1 -0
- package/src/context/request-context.d.ts +184 -0
- package/src/context/request-context.js +209 -0
- package/src/context/request-context.js.map +1 -0
- package/src/context/request-context.provider.d.ts +37 -0
- package/src/context/request-context.provider.js +51 -0
- package/src/context/request-context.provider.js.map +1 -0
- package/src/context/session-key.provider.d.ts +45 -0
- package/src/context/session-key.provider.js +65 -0
- package/src/context/session-key.provider.js.map +1 -0
- package/src/context/trace-context.d.ts +43 -0
- package/src/context/trace-context.js +142 -0
- package/src/context/trace-context.js.map +1 -0
- package/src/errors/index.d.ts +1 -1
- package/src/errors/index.js +4 -1
- package/src/errors/index.js.map +1 -1
- package/src/errors/mcp.error.d.ts +16 -0
- package/src/errors/mcp.error.js +29 -1
- package/src/errors/mcp.error.js.map +1 -1
- package/src/flows/flow.instance.d.ts +16 -0
- package/src/flows/flow.instance.js +166 -80
- package/src/flows/flow.instance.js.map +1 -1
- package/src/flows/flow.registry.d.ts +5 -0
- package/src/flows/flow.registry.js +45 -3
- package/src/flows/flow.registry.js.map +1 -1
- package/src/front-mcp/front-mcp.d.ts +12 -0
- package/src/front-mcp/front-mcp.js +22 -3
- package/src/front-mcp/front-mcp.js.map +1 -1
- package/src/front-mcp/front-mcp.providers.d.ts +474 -1
- package/src/front-mcp/front-mcp.providers.js +2 -1
- package/src/front-mcp/front-mcp.providers.js.map +1 -1
- package/src/front-mcp/index.d.ts +1 -0
- package/src/front-mcp/index.js +3 -0
- package/src/front-mcp/index.js.map +1 -1
- package/src/front-mcp/serverless-handler.d.ts +28 -0
- package/src/front-mcp/serverless-handler.js +61 -0
- package/src/front-mcp/serverless-handler.js.map +1 -0
- package/src/hooks/hooks.utils.d.ts +1 -1
- package/src/hooks/hooks.utils.js +10 -3
- package/src/hooks/hooks.utils.js.map +1 -1
- package/src/index.d.ts +9 -5
- package/src/index.js +21 -1
- package/src/index.js.map +1 -1
- package/src/logger/instances/instance.logger.js +0 -1
- package/src/logger/instances/instance.logger.js.map +1 -1
- package/src/logging/flows/set-level.flow.d.ts +6 -8
- package/src/notification/notification.service.js +5 -1
- package/src/notification/notification.service.js.map +1 -1
- package/src/prompt/flows/get-prompt.flow.d.ts +14 -8
- package/src/prompt/flows/prompts-list.flow.d.ts +8 -7
- package/src/provider/provider.registry.d.ts +97 -5
- package/src/provider/provider.registry.js +306 -9
- package/src/provider/provider.registry.js.map +1 -1
- package/src/provider/provider.types.d.ts +21 -3
- package/src/provider/provider.types.js.map +1 -1
- package/src/resource/flows/read-resource.flow.d.ts +8 -9
- package/src/resource/flows/resource-templates-list.flow.d.ts +8 -7
- package/src/resource/flows/resources-list.flow.d.ts +8 -7
- package/src/resource/flows/subscribe-resource.flow.d.ts +6 -8
- package/src/resource/flows/unsubscribe-resource.flow.d.ts +6 -8
- package/src/scope/flows/http.request.flow.js +43 -7
- package/src/scope/flows/http.request.flow.js.map +1 -1
- package/src/scope/scope.instance.js +12 -5
- package/src/scope/scope.instance.js.map +1 -1
- package/src/server/adapters/base.host.adapter.d.ts +9 -0
- package/src/server/adapters/base.host.adapter.js.map +1 -1
- package/src/server/adapters/express.host.adapter.d.ts +12 -0
- package/src/server/adapters/express.host.adapter.js +21 -1
- package/src/server/adapters/express.host.adapter.js.map +1 -1
- package/src/server/server.instance.d.ts +3 -0
- package/src/server/server.instance.js +14 -7
- package/src/server/server.instance.js.map +1 -1
- package/src/store/adapters/store.vercel-kv.adapter.d.ts +86 -0
- package/src/store/adapters/store.vercel-kv.adapter.js +155 -0
- package/src/store/adapters/store.vercel-kv.adapter.js.map +1 -0
- package/src/store/index.d.ts +2 -0
- package/src/store/index.js +2 -0
- package/src/store/index.js.map +1 -1
- package/src/store/store.factory.d.ts +86 -0
- package/src/store/store.factory.js +194 -0
- package/src/store/store.factory.js.map +1 -0
- package/src/tool/flows/call-tool.flow.d.ts +38 -19
- package/src/tool/flows/call-tool.flow.js +240 -194
- package/src/tool/flows/call-tool.flow.js.map +1 -1
- package/src/tool/flows/tools-list.flow.d.ts +14 -17
- package/src/tool/flows/tools-list.flow.js +84 -33
- package/src/tool/flows/tools-list.flow.js.map +1 -1
- package/src/tool/tool.instance.d.ts +1 -4
- package/src/tool/ui/index.d.ts +4 -4
- package/src/tool/ui/index.js +4 -4
- package/src/tool/ui/index.js.map +1 -1
- package/src/tool/ui/platform-adapters.d.ts +2 -2
- package/src/tool/ui/platform-adapters.js +3 -3
- package/src/tool/ui/platform-adapters.js.map +1 -1
- package/src/tool/ui/template-helpers.d.ts +5 -7
- package/src/tool/ui/template-helpers.js +9 -26
- package/src/tool/ui/template-helpers.js.map +1 -1
- package/src/tool/ui/ui-resource.handler.d.ts +1 -1
- package/src/tool/ui/ui-resource.handler.js +5 -5
- package/src/tool/ui/ui-resource.handler.js.map +1 -1
- package/src/transport/adapters/transport.streamable-http.adapter.js +1 -0
- package/src/transport/adapters/transport.streamable-http.adapter.js.map +1 -1
- package/src/transport/flows/handle.sse.flow.js +9 -2
- package/src/transport/flows/handle.sse.flow.js.map +1 -1
- package/src/transport/flows/handle.streamable-http.flow.js +63 -6
- package/src/transport/flows/handle.streamable-http.flow.js.map +1 -1
- package/src/transport/mcp-handlers/complete-request.handler.d.ts +4 -15
- package/src/transport/mcp-handlers/get-prompt-request.handler.d.ts +5 -15
- package/src/transport/mcp-handlers/index.d.ts +67 -195
- package/src/transport/mcp-handlers/initialize-request.handler.js +12 -2
- package/src/transport/mcp-handlers/initialize-request.handler.js.map +1 -1
- package/src/transport/mcp-handlers/list-prompts-request.handler.d.ts +5 -15
- package/src/transport/mcp-handlers/list-resource-templates-request.handler.d.ts +5 -15
- package/src/transport/mcp-handlers/list-resources-request.handler.d.ts +5 -15
- package/src/transport/mcp-handlers/list-tools-request.handler.d.ts +5 -15
- package/src/transport/mcp-handlers/logging-set-level-request.handler.d.ts +3 -14
- package/src/transport/mcp-handlers/read-resource-request.handler.d.ts +4 -15
- package/src/transport/mcp-handlers/subscribe-request.handler.d.ts +3 -14
- package/src/transport/mcp-handlers/unsubscribe-request.handler.d.ts +3 -14
- package/src/transport/transport.registry.d.ts +72 -4
- package/src/transport/transport.registry.js +342 -11
- package/src/transport/transport.registry.js.map +1 -1
- package/src/auth/ui/htmx-templates.js.map +0 -1
- package/src/common/providers/session.provider.d.ts +0 -13
- package/src/common/providers/session.provider.js +0 -27
- package/src/common/providers/session.provider.js.map +0 -1
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Vercel KV Store Adapter
|
|
4
|
+
*
|
|
5
|
+
* Store adapter implementation using Vercel KV (edge-compatible REST-based key-value store).
|
|
6
|
+
* Uses dynamic import to avoid bundling @vercel/kv for non-Vercel deployments.
|
|
7
|
+
*
|
|
8
|
+
* @see https://vercel.com/docs/storage/vercel-kv
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.ScopedVercelKvStore = void 0;
|
|
12
|
+
const store_base_adapter_1 = require("./store.base.adapter");
|
|
13
|
+
/**
|
|
14
|
+
* Vercel KV Store Adapter
|
|
15
|
+
*
|
|
16
|
+
* Implements the StoreDriver interface using Vercel KV.
|
|
17
|
+
* Note: Pub/Sub is not supported by Vercel KV (REST-based).
|
|
18
|
+
* The base class provides no-op implementations for publish/subscribe.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const store = new ScopedVercelKvStore({
|
|
23
|
+
* url: process.env.KV_REST_API_URL,
|
|
24
|
+
* token: process.env.KV_REST_API_TOKEN,
|
|
25
|
+
* keyPrefix: 'myapp:',
|
|
26
|
+
* });
|
|
27
|
+
* await store.connect();
|
|
28
|
+
* await store.set('key', 'value', { ttlSeconds: 3600 });
|
|
29
|
+
* const value = await store.get('key');
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
class ScopedVercelKvStore extends store_base_adapter_1.StoreBaseAdapter {
|
|
33
|
+
kv = null;
|
|
34
|
+
opts;
|
|
35
|
+
constructor(opts = {}) {
|
|
36
|
+
super();
|
|
37
|
+
this.opts = opts;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Connect to Vercel KV
|
|
41
|
+
* Uses dynamic import to avoid bundling @vercel/kv when not used
|
|
42
|
+
*/
|
|
43
|
+
async connect() {
|
|
44
|
+
if (this.kv)
|
|
45
|
+
return;
|
|
46
|
+
// Dynamic import for tree-shaking
|
|
47
|
+
const vercelKv = await import('@vercel/kv');
|
|
48
|
+
const url = this.opts.url || process.env['KV_REST_API_URL'];
|
|
49
|
+
const token = this.opts.token || process.env['KV_REST_API_TOKEN'];
|
|
50
|
+
if (!url || !token) {
|
|
51
|
+
throw new Error('Vercel KV requires url and token. Set KV_REST_API_URL and KV_REST_API_TOKEN environment variables or provide them in config.');
|
|
52
|
+
}
|
|
53
|
+
// Cast to our interface to avoid type compatibility issues
|
|
54
|
+
this.kv = vercelKv.createClient({ url, token });
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Disconnect from Vercel KV
|
|
58
|
+
* Vercel KV uses REST API, so there's no persistent connection to close
|
|
59
|
+
*/
|
|
60
|
+
async disconnect() {
|
|
61
|
+
this.kv = null;
|
|
62
|
+
}
|
|
63
|
+
ensureConnected() {
|
|
64
|
+
if (!this.kv) {
|
|
65
|
+
throw new Error('Vercel KV not connected. Call connect() first.');
|
|
66
|
+
}
|
|
67
|
+
return this.kv;
|
|
68
|
+
}
|
|
69
|
+
prefixKey(key) {
|
|
70
|
+
if (!key || key.trim() === '') {
|
|
71
|
+
throw new Error('[ScopedVercelKvStore] key cannot be empty');
|
|
72
|
+
}
|
|
73
|
+
return this.opts.keyPrefix ? `${this.opts.keyPrefix}${key}` : key;
|
|
74
|
+
}
|
|
75
|
+
async get(key) {
|
|
76
|
+
const kv = this.ensureConnected();
|
|
77
|
+
const result = await kv.get(this.prefixKey(key));
|
|
78
|
+
return result ?? null;
|
|
79
|
+
}
|
|
80
|
+
async set(key, value, opts) {
|
|
81
|
+
const kv = this.ensureConnected();
|
|
82
|
+
const prefixedKey = this.prefixKey(key);
|
|
83
|
+
if (opts?.ttlSeconds && opts.ttlSeconds > 0) {
|
|
84
|
+
await kv.set(prefixedKey, value, { ex: Math.floor(opts.ttlSeconds) });
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
await kv.set(prefixedKey, value);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async del(key) {
|
|
91
|
+
const kv = this.ensureConnected();
|
|
92
|
+
await kv.del(this.prefixKey(key));
|
|
93
|
+
}
|
|
94
|
+
async exists(key) {
|
|
95
|
+
const kv = this.ensureConnected();
|
|
96
|
+
const result = await kv.exists(this.prefixKey(key));
|
|
97
|
+
return result === 1;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get multiple keys
|
|
101
|
+
* Uses Vercel KV's mget for efficiency
|
|
102
|
+
*/
|
|
103
|
+
async mget(keys) {
|
|
104
|
+
if (!keys.length)
|
|
105
|
+
return [];
|
|
106
|
+
const kv = this.ensureConnected();
|
|
107
|
+
const prefixedKeys = keys.map((k) => this.prefixKey(k));
|
|
108
|
+
const results = await kv.mget(...prefixedKeys);
|
|
109
|
+
return results.map((r) => r ?? null);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Set multiple keys
|
|
113
|
+
* Uses Vercel KV's mset for efficiency (no TTL support in bulk)
|
|
114
|
+
* Falls back to sequential sets for TTL support
|
|
115
|
+
*/
|
|
116
|
+
async mset(entries) {
|
|
117
|
+
if (!entries.length)
|
|
118
|
+
return;
|
|
119
|
+
const kv = this.ensureConnected();
|
|
120
|
+
const hasTtl = entries.some((e) => e.opts?.ttlSeconds && e.opts.ttlSeconds > 0);
|
|
121
|
+
if (hasTtl) {
|
|
122
|
+
// Sequential sets to support TTL
|
|
123
|
+
for (const { key, value, opts } of entries) {
|
|
124
|
+
await this.set(key, value, opts);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
// Bulk set without TTL
|
|
129
|
+
const kvPairs = {};
|
|
130
|
+
for (const { key, value } of entries) {
|
|
131
|
+
kvPairs[this.prefixKey(key)] = value;
|
|
132
|
+
}
|
|
133
|
+
await kv.mset(kvPairs);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async incr(key) {
|
|
137
|
+
const kv = this.ensureConnected();
|
|
138
|
+
return kv.incr(this.prefixKey(key));
|
|
139
|
+
}
|
|
140
|
+
async decr(key) {
|
|
141
|
+
const kv = this.ensureConnected();
|
|
142
|
+
return kv.decr(this.prefixKey(key));
|
|
143
|
+
}
|
|
144
|
+
async expire(key, ttlSeconds) {
|
|
145
|
+
const kv = this.ensureConnected();
|
|
146
|
+
await kv.expire(this.prefixKey(key), Math.floor(ttlSeconds));
|
|
147
|
+
}
|
|
148
|
+
async ttl(key) {
|
|
149
|
+
const kv = this.ensureConnected();
|
|
150
|
+
const t = await kv.ttl(this.prefixKey(key));
|
|
151
|
+
return t < 0 ? null : t;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
exports.ScopedVercelKvStore = ScopedVercelKvStore;
|
|
155
|
+
//# sourceMappingURL=store.vercel-kv.adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.vercel-kv.adapter.js","sourceRoot":"","sources":["../../../../src/store/adapters/store.vercel-kv.adapter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Vercel KV Store Adapter\n *\n * Store adapter implementation using Vercel KV (edge-compatible REST-based key-value store).\n * Uses dynamic import to avoid bundling @vercel/kv for non-Vercel deployments.\n *\n * @see https://vercel.com/docs/storage/vercel-kv\n */\n\nimport { StoreBaseAdapter } from './store.base.adapter';\nimport type { SetOptions } from '../store.types';\n\n// Interface for the Vercel KV client (matches @vercel/kv API)\ninterface VercelKVClient {\n get<T = unknown>(key: string): Promise<T | null>;\n set(key: string, value: unknown, options?: { ex?: number; px?: number }): Promise<void>;\n del(...keys: string[]): Promise<number>;\n exists(...keys: string[]): Promise<number>;\n mget<T = unknown>(...keys: string[]): Promise<(T | null)[]>;\n mset(data: Record<string, unknown>): Promise<void>;\n incr(key: string): Promise<number>;\n decr(key: string): Promise<number>;\n expire(key: string, seconds: number): Promise<number>;\n pexpire(key: string, milliseconds: number): Promise<number>;\n ttl(key: string): Promise<number>;\n}\n\nexport interface VercelKvAdapterOptions {\n /**\n * KV REST API URL\n * @default process.env.KV_REST_API_URL\n */\n url?: string;\n\n /**\n * KV REST API Token\n * @default process.env.KV_REST_API_TOKEN\n */\n token?: string;\n\n /**\n * Key prefix for all keys\n * @default ''\n */\n keyPrefix?: string;\n}\n\n/**\n * Vercel KV Store Adapter\n *\n * Implements the StoreDriver interface using Vercel KV.\n * Note: Pub/Sub is not supported by Vercel KV (REST-based).\n * The base class provides no-op implementations for publish/subscribe.\n *\n * @example\n * ```typescript\n * const store = new ScopedVercelKvStore({\n * url: process.env.KV_REST_API_URL,\n * token: process.env.KV_REST_API_TOKEN,\n * keyPrefix: 'myapp:',\n * });\n * await store.connect();\n * await store.set('key', 'value', { ttlSeconds: 3600 });\n * const value = await store.get('key');\n * ```\n */\nexport class ScopedVercelKvStore extends StoreBaseAdapter {\n private kv: VercelKVClient | null = null;\n private readonly opts: VercelKvAdapterOptions;\n\n constructor(opts: VercelKvAdapterOptions = {}) {\n super();\n this.opts = opts;\n }\n\n /**\n * Connect to Vercel KV\n * Uses dynamic import to avoid bundling @vercel/kv when not used\n */\n async connect(): Promise<void> {\n if (this.kv) return;\n\n // Dynamic import for tree-shaking\n const vercelKv = await import('@vercel/kv');\n\n const url = this.opts.url || process.env['KV_REST_API_URL'];\n const token = this.opts.token || process.env['KV_REST_API_TOKEN'];\n\n if (!url || !token) {\n throw new Error(\n 'Vercel KV requires url and token. Set KV_REST_API_URL and KV_REST_API_TOKEN environment variables or provide them in config.',\n );\n }\n\n // Cast to our interface to avoid type compatibility issues\n this.kv = vercelKv.createClient({ url, token }) as unknown as VercelKVClient;\n }\n\n /**\n * Disconnect from Vercel KV\n * Vercel KV uses REST API, so there's no persistent connection to close\n */\n async disconnect(): Promise<void> {\n this.kv = null;\n }\n\n private ensureConnected(): VercelKVClient {\n if (!this.kv) {\n throw new Error('Vercel KV not connected. Call connect() first.');\n }\n return this.kv;\n }\n\n private prefixKey(key: string): string {\n if (!key || key.trim() === '') {\n throw new Error('[ScopedVercelKvStore] key cannot be empty');\n }\n return this.opts.keyPrefix ? `${this.opts.keyPrefix}${key}` : key;\n }\n\n async get(key: string): Promise<string | null> {\n const kv = this.ensureConnected();\n const result = await kv.get<string>(this.prefixKey(key));\n return result ?? null;\n }\n\n async set(key: string, value: string, opts?: SetOptions): Promise<void> {\n const kv = this.ensureConnected();\n const prefixedKey = this.prefixKey(key);\n\n if (opts?.ttlSeconds && opts.ttlSeconds > 0) {\n await kv.set(prefixedKey, value, { ex: Math.floor(opts.ttlSeconds) });\n } else {\n await kv.set(prefixedKey, value);\n }\n }\n\n async del(key: string): Promise<void> {\n const kv = this.ensureConnected();\n await kv.del(this.prefixKey(key));\n }\n\n async exists(key: string): Promise<boolean> {\n const kv = this.ensureConnected();\n const result = await kv.exists(this.prefixKey(key));\n return result === 1;\n }\n\n /**\n * Get multiple keys\n * Uses Vercel KV's mget for efficiency\n */\n override async mget(keys: string[]): Promise<(string | null)[]> {\n if (!keys.length) return [];\n const kv = this.ensureConnected();\n const prefixedKeys = keys.map((k) => this.prefixKey(k));\n const results = await kv.mget<string>(...prefixedKeys);\n return results.map((r) => r ?? null);\n }\n\n /**\n * Set multiple keys\n * Uses Vercel KV's mset for efficiency (no TTL support in bulk)\n * Falls back to sequential sets for TTL support\n */\n override async mset(entries: Array<{ key: string; value: string; opts?: SetOptions }>): Promise<void> {\n if (!entries.length) return;\n\n const kv = this.ensureConnected();\n const hasTtl = entries.some((e) => e.opts?.ttlSeconds && e.opts.ttlSeconds > 0);\n\n if (hasTtl) {\n // Sequential sets to support TTL\n for (const { key, value, opts } of entries) {\n await this.set(key, value, opts);\n }\n } else {\n // Bulk set without TTL\n const kvPairs: Record<string, string> = {};\n for (const { key, value } of entries) {\n kvPairs[this.prefixKey(key)] = value;\n }\n await kv.mset(kvPairs);\n }\n }\n\n async incr(key: string): Promise<number> {\n const kv = this.ensureConnected();\n return kv.incr(this.prefixKey(key));\n }\n\n async decr(key: string): Promise<number> {\n const kv = this.ensureConnected();\n return kv.decr(this.prefixKey(key));\n }\n\n async expire(key: string, ttlSeconds: number): Promise<void> {\n const kv = this.ensureConnected();\n await kv.expire(this.prefixKey(key), Math.floor(ttlSeconds));\n }\n\n async ttl(key: string): Promise<number | null> {\n const kv = this.ensureConnected();\n const t = await kv.ttl(this.prefixKey(key));\n return t < 0 ? null : t;\n }\n\n // Note: Pub/Sub is not supported by Vercel KV (REST-based)\n // Base class provides no-op implementations that return 0 for publish\n // and a no-op unsubscribe function for subscribe\n}\n"]}
|
package/src/store/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export * from './store.tokens';
|
|
|
3
3
|
export * from './store.utils';
|
|
4
4
|
export * from './store.registry';
|
|
5
5
|
export * from './store.helpers';
|
|
6
|
+
export * from './store.factory';
|
|
6
7
|
export * from './adapters/store.base.adapter';
|
|
7
8
|
export * from './adapters/store.redis.adapter';
|
|
8
9
|
export * from './adapters/store.memory.adapter';
|
|
10
|
+
export * from './adapters/store.vercel-kv.adapter';
|
package/src/store/index.js
CHANGED
|
@@ -6,7 +6,9 @@ tslib_1.__exportStar(require("./store.tokens"), exports);
|
|
|
6
6
|
tslib_1.__exportStar(require("./store.utils"), exports);
|
|
7
7
|
tslib_1.__exportStar(require("./store.registry"), exports);
|
|
8
8
|
tslib_1.__exportStar(require("./store.helpers"), exports);
|
|
9
|
+
tslib_1.__exportStar(require("./store.factory"), exports);
|
|
9
10
|
tslib_1.__exportStar(require("./adapters/store.base.adapter"), exports);
|
|
10
11
|
tslib_1.__exportStar(require("./adapters/store.redis.adapter"), exports);
|
|
11
12
|
tslib_1.__exportStar(require("./adapters/store.memory.adapter"), exports);
|
|
13
|
+
tslib_1.__exportStar(require("./adapters/store.vercel-kv.adapter"), exports);
|
|
12
14
|
//# sourceMappingURL=index.js.map
|
package/src/store/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/store/index.ts"],"names":[],"mappings":";;;AAAA,wDAA8B;AAC9B,yDAA+B;AAC/B,wDAA8B;AAC9B,2DAAiC;AACjC,0DAAgC;AAChC,wEAA8C;AAC9C,yEAA+C;AAC/C,0EAAgD","sourcesContent":["export * from './store.types';\nexport * from './store.tokens';\nexport * from './store.utils';\nexport * from './store.registry';\nexport * from './store.helpers';\nexport * from './adapters/store.base.adapter';\nexport * from './adapters/store.redis.adapter';\nexport * from './adapters/store.memory.adapter';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/store/index.ts"],"names":[],"mappings":";;;AAAA,wDAA8B;AAC9B,yDAA+B;AAC/B,wDAA8B;AAC9B,2DAAiC;AACjC,0DAAgC;AAChC,0DAAgC;AAChC,wEAA8C;AAC9C,yEAA+C;AAC/C,0EAAgD;AAChD,6EAAmD","sourcesContent":["export * from './store.types';\nexport * from './store.tokens';\nexport * from './store.utils';\nexport * from './store.registry';\nexport * from './store.helpers';\nexport * from './store.factory';\nexport * from './adapters/store.base.adapter';\nexport * from './adapters/store.redis.adapter';\nexport * from './adapters/store.memory.adapter';\nexport * from './adapters/store.vercel-kv.adapter';\n"]}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage Factory
|
|
3
|
+
*
|
|
4
|
+
* Factory functions for creating store drivers and session stores
|
|
5
|
+
* based on configuration. Supports both Redis and Vercel KV providers.
|
|
6
|
+
*/
|
|
7
|
+
import type { StoreDriver } from './store.types';
|
|
8
|
+
import type { SessionStore } from '../auth/session/transport-session.types';
|
|
9
|
+
import type { FrontMcpLogger } from '../common/interfaces/logger.interface';
|
|
10
|
+
import { type RedisOptions, type PubsubOptions } from '../common/types/options/redis.options';
|
|
11
|
+
/**
|
|
12
|
+
* Create a store driver based on configuration
|
|
13
|
+
*
|
|
14
|
+
* @param options - Storage configuration (Redis or Vercel KV)
|
|
15
|
+
* @returns A store driver instance (not connected)
|
|
16
|
+
*
|
|
17
|
+
* @example Redis
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const driver = createStoreDriver({
|
|
20
|
+
* provider: 'redis',
|
|
21
|
+
* host: 'localhost',
|
|
22
|
+
* port: 6379,
|
|
23
|
+
* });
|
|
24
|
+
* await driver.connect();
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @example Vercel KV
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const driver = createStoreDriver({
|
|
30
|
+
* provider: 'vercel-kv',
|
|
31
|
+
* // Uses KV_REST_API_URL and KV_REST_API_TOKEN env vars
|
|
32
|
+
* });
|
|
33
|
+
* await driver.connect();
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function createStoreDriver(options: RedisOptions): StoreDriver;
|
|
37
|
+
/**
|
|
38
|
+
* Create a session store based on configuration
|
|
39
|
+
*
|
|
40
|
+
* @param options - Storage configuration (Redis or Vercel KV)
|
|
41
|
+
* @param logger - Optional logger instance
|
|
42
|
+
* @returns A session store instance
|
|
43
|
+
*
|
|
44
|
+
* @example Redis
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const store = await createSessionStore({
|
|
47
|
+
* provider: 'redis',
|
|
48
|
+
* host: 'localhost',
|
|
49
|
+
* port: 6379,
|
|
50
|
+
* });
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @example Vercel KV
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const store = await createSessionStore({
|
|
56
|
+
* provider: 'vercel-kv',
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare function createSessionStore(options: RedisOptions, logger?: FrontMcpLogger): Promise<SessionStore>;
|
|
61
|
+
/**
|
|
62
|
+
* Create a session store synchronously (for backwards compatibility)
|
|
63
|
+
* Note: For Vercel KV, use createSessionStore() instead as it requires async connect
|
|
64
|
+
*
|
|
65
|
+
* @param options - Storage configuration (Redis only)
|
|
66
|
+
* @param logger - Optional logger instance
|
|
67
|
+
* @returns A session store instance
|
|
68
|
+
*/
|
|
69
|
+
export declare function createSessionStoreSync(options: RedisOptions, logger?: FrontMcpLogger): SessionStore;
|
|
70
|
+
/**
|
|
71
|
+
* Create a pub/sub store for resource subscriptions
|
|
72
|
+
*
|
|
73
|
+
* Pub/Sub requires Redis - Vercel KV does not support pub/sub operations.
|
|
74
|
+
* Use this when you need resource subscriptions with Vercel KV for sessions.
|
|
75
|
+
*
|
|
76
|
+
* @param options - Pub/sub configuration (Redis only)
|
|
77
|
+
* @returns A Redis store driver with pub/sub support
|
|
78
|
+
*
|
|
79
|
+
* @example Hybrid config
|
|
80
|
+
* ```typescript
|
|
81
|
+
* // Use Vercel KV for sessions, Redis for pub/sub
|
|
82
|
+
* const sessionStore = await createSessionStore({ provider: 'vercel-kv' });
|
|
83
|
+
* const pubsubStore = createPubsubStore({ host: 'localhost', port: 6379 });
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export declare function createPubsubStore(options: PubsubOptions): StoreDriver;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Storage Factory
|
|
4
|
+
*
|
|
5
|
+
* Factory functions for creating store drivers and session stores
|
|
6
|
+
* based on configuration. Supports both Redis and Vercel KV providers.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.createStoreDriver = createStoreDriver;
|
|
10
|
+
exports.createSessionStore = createSessionStore;
|
|
11
|
+
exports.createSessionStoreSync = createSessionStoreSync;
|
|
12
|
+
exports.createPubsubStore = createPubsubStore;
|
|
13
|
+
const redis_options_1 = require("../common/types/options/redis.options");
|
|
14
|
+
/**
|
|
15
|
+
* Create a store driver based on configuration
|
|
16
|
+
*
|
|
17
|
+
* @param options - Storage configuration (Redis or Vercel KV)
|
|
18
|
+
* @returns A store driver instance (not connected)
|
|
19
|
+
*
|
|
20
|
+
* @example Redis
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const driver = createStoreDriver({
|
|
23
|
+
* provider: 'redis',
|
|
24
|
+
* host: 'localhost',
|
|
25
|
+
* port: 6379,
|
|
26
|
+
* });
|
|
27
|
+
* await driver.connect();
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @example Vercel KV
|
|
31
|
+
* ```typescript
|
|
32
|
+
* const driver = createStoreDriver({
|
|
33
|
+
* provider: 'vercel-kv',
|
|
34
|
+
* // Uses KV_REST_API_URL and KV_REST_API_TOKEN env vars
|
|
35
|
+
* });
|
|
36
|
+
* await driver.connect();
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
function createStoreDriver(options) {
|
|
40
|
+
if ((0, redis_options_1.isVercelKvProvider)(options)) {
|
|
41
|
+
return createVercelKvStoreDriver(options);
|
|
42
|
+
}
|
|
43
|
+
if ((0, redis_options_1.isRedisProvider)(options)) {
|
|
44
|
+
return createRedisStoreDriver(options);
|
|
45
|
+
}
|
|
46
|
+
// Fallback for legacy format without provider field
|
|
47
|
+
return createRedisStoreDriver(options);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Create a Redis store driver
|
|
51
|
+
*/
|
|
52
|
+
function createRedisStoreDriver(options) {
|
|
53
|
+
// Lazy import to avoid bundling ioredis when not used
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
55
|
+
const { ScopedRedisStore } = require('./adapters/store.redis.adapter');
|
|
56
|
+
return new ScopedRedisStore({
|
|
57
|
+
options: {
|
|
58
|
+
host: options.host,
|
|
59
|
+
port: options.port,
|
|
60
|
+
password: options.password,
|
|
61
|
+
db: options.db,
|
|
62
|
+
tls: options.tls ? {} : undefined,
|
|
63
|
+
keyPrefix: options.keyPrefix,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Create a Vercel KV store driver
|
|
69
|
+
*/
|
|
70
|
+
function createVercelKvStoreDriver(options) {
|
|
71
|
+
// Lazy import to avoid bundling @vercel/kv when not used
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
73
|
+
const { ScopedVercelKvStore } = require('./adapters/store.vercel-kv.adapter');
|
|
74
|
+
return new ScopedVercelKvStore({
|
|
75
|
+
url: options.url,
|
|
76
|
+
token: options.token,
|
|
77
|
+
keyPrefix: options.keyPrefix,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Create a session store based on configuration
|
|
82
|
+
*
|
|
83
|
+
* @param options - Storage configuration (Redis or Vercel KV)
|
|
84
|
+
* @param logger - Optional logger instance
|
|
85
|
+
* @returns A session store instance
|
|
86
|
+
*
|
|
87
|
+
* @example Redis
|
|
88
|
+
* ```typescript
|
|
89
|
+
* const store = await createSessionStore({
|
|
90
|
+
* provider: 'redis',
|
|
91
|
+
* host: 'localhost',
|
|
92
|
+
* port: 6379,
|
|
93
|
+
* });
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* @example Vercel KV
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const store = await createSessionStore({
|
|
99
|
+
* provider: 'vercel-kv',
|
|
100
|
+
* });
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
async function createSessionStore(options, logger) {
|
|
104
|
+
if ((0, redis_options_1.isVercelKvProvider)(options)) {
|
|
105
|
+
return createVercelKvSessionStore(options, logger);
|
|
106
|
+
}
|
|
107
|
+
if ((0, redis_options_1.isRedisProvider)(options)) {
|
|
108
|
+
return createRedisSessionStore(options, logger);
|
|
109
|
+
}
|
|
110
|
+
// Fallback for legacy format without provider field
|
|
111
|
+
return createRedisSessionStore(options, logger);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Create a Redis session store
|
|
115
|
+
*/
|
|
116
|
+
async function createRedisSessionStore(options, logger) {
|
|
117
|
+
// Lazy require to avoid bundling ioredis when not used
|
|
118
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
119
|
+
const { RedisSessionStore } = require('../auth/session/redis-session.store');
|
|
120
|
+
return new RedisSessionStore({
|
|
121
|
+
host: options.host,
|
|
122
|
+
port: options.port,
|
|
123
|
+
password: options.password,
|
|
124
|
+
db: options.db,
|
|
125
|
+
tls: options.tls,
|
|
126
|
+
keyPrefix: options.keyPrefix ? `${options.keyPrefix}session:` : 'mcp:session:',
|
|
127
|
+
defaultTtlMs: options.defaultTtlMs,
|
|
128
|
+
}, logger);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Create a Vercel KV session store
|
|
132
|
+
*/
|
|
133
|
+
async function createVercelKvSessionStore(options, logger) {
|
|
134
|
+
// Lazy require to avoid bundling @vercel/kv when not used
|
|
135
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
136
|
+
const { VercelKvSessionStore } = require('../auth/session/vercel-kv-session.store');
|
|
137
|
+
const store = new VercelKvSessionStore({
|
|
138
|
+
url: options.url,
|
|
139
|
+
token: options.token,
|
|
140
|
+
keyPrefix: options.keyPrefix ? `${options.keyPrefix}session:` : 'mcp:session:',
|
|
141
|
+
defaultTtlMs: options.defaultTtlMs,
|
|
142
|
+
}, logger);
|
|
143
|
+
// Pre-connect for Vercel KV
|
|
144
|
+
await store.connect();
|
|
145
|
+
return store;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Create a session store synchronously (for backwards compatibility)
|
|
149
|
+
* Note: For Vercel KV, use createSessionStore() instead as it requires async connect
|
|
150
|
+
*
|
|
151
|
+
* @param options - Storage configuration (Redis only)
|
|
152
|
+
* @param logger - Optional logger instance
|
|
153
|
+
* @returns A session store instance
|
|
154
|
+
*/
|
|
155
|
+
function createSessionStoreSync(options, logger) {
|
|
156
|
+
if ((0, redis_options_1.isVercelKvProvider)(options)) {
|
|
157
|
+
throw new Error('Vercel KV session store requires async initialization. Use createSessionStore() instead.');
|
|
158
|
+
}
|
|
159
|
+
// Redis only - synchronous creation
|
|
160
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
161
|
+
const { RedisSessionStore } = require('../auth/session/redis-session.store');
|
|
162
|
+
const redisOptions = (0, redis_options_1.isRedisProvider)(options) ? options : options;
|
|
163
|
+
return new RedisSessionStore({
|
|
164
|
+
host: redisOptions.host,
|
|
165
|
+
port: redisOptions.port,
|
|
166
|
+
password: redisOptions.password,
|
|
167
|
+
db: redisOptions.db,
|
|
168
|
+
tls: redisOptions.tls,
|
|
169
|
+
keyPrefix: redisOptions.keyPrefix ? `${redisOptions.keyPrefix}session:` : 'mcp:session:',
|
|
170
|
+
defaultTtlMs: redisOptions.defaultTtlMs,
|
|
171
|
+
}, logger);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Create a pub/sub store for resource subscriptions
|
|
175
|
+
*
|
|
176
|
+
* Pub/Sub requires Redis - Vercel KV does not support pub/sub operations.
|
|
177
|
+
* Use this when you need resource subscriptions with Vercel KV for sessions.
|
|
178
|
+
*
|
|
179
|
+
* @param options - Pub/sub configuration (Redis only)
|
|
180
|
+
* @returns A Redis store driver with pub/sub support
|
|
181
|
+
*
|
|
182
|
+
* @example Hybrid config
|
|
183
|
+
* ```typescript
|
|
184
|
+
* // Use Vercel KV for sessions, Redis for pub/sub
|
|
185
|
+
* const sessionStore = await createSessionStore({ provider: 'vercel-kv' });
|
|
186
|
+
* const pubsubStore = createPubsubStore({ host: 'localhost', port: 6379 });
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
function createPubsubStore(options) {
|
|
190
|
+
// PubsubOptions only allows Redis provider, so we can safely cast
|
|
191
|
+
const redisOptions = options;
|
|
192
|
+
return createRedisStoreDriver(redisOptions);
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=store.factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.factory.js","sourceRoot":"","sources":["../../../src/store/store.factory.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAuCH,8CAWC;AA4DD,gDAWC;AA2DD,wDAsBC;AAkBD,8CAIC;AA3ND,yEAO+C;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,SAAgB,iBAAiB,CAAC,OAAqB;IACrD,IAAI,IAAA,kCAAkB,EAAC,OAAO,CAAC,EAAE,CAAC;QAChC,OAAO,yBAAyB,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,IAAA,+BAAe,EAAC,OAAO,CAAC,EAAE,CAAC;QAC7B,OAAO,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,oDAAoD;IACpD,OAAO,sBAAsB,CAAC,OAA+B,CAAC,CAAC;AACjE,CAAC;AAED;;GAEG;AACH,SAAS,sBAAsB,CAAC,OAA6B;IAC3D,sDAAsD;IACtD,iEAAiE;IACjE,MAAM,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,gCAAgC,CAAC,CAAC;IAEvE,OAAO,IAAI,gBAAgB,CAAC;QAC1B,OAAO,EAAE;YACP,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS;YACjC,SAAS,EAAE,OAAO,CAAC,SAAS;SAC7B;KACF,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,yBAAyB,CAAC,OAAgC;IACjE,yDAAyD;IACzD,iEAAiE;IACjE,MAAM,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,oCAAoC,CAAC,CAAC;IAE9E,OAAO,IAAI,mBAAmB,CAAC;QAC7B,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACI,KAAK,UAAU,kBAAkB,CAAC,OAAqB,EAAE,MAAuB;IACrF,IAAI,IAAA,kCAAkB,EAAC,OAAO,CAAC,EAAE,CAAC;QAChC,OAAO,0BAA0B,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,IAAA,+BAAe,EAAC,OAAO,CAAC,EAAE,CAAC;QAC7B,OAAO,uBAAuB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAClD,CAAC;IAED,oDAAoD;IACpD,OAAO,uBAAuB,CAAC,OAA+B,EAAE,MAAM,CAAC,CAAC;AAC1E,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,uBAAuB,CAAC,OAA6B,EAAE,MAAuB;IAC3F,uDAAuD;IACvD,iEAAiE;IACjE,MAAM,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,qCAAqC,CAAC,CAAC;IAE7E,OAAO,IAAI,iBAAiB,CAC1B;QACE,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,cAAc;QAC9E,YAAY,EAAE,OAAO,CAAC,YAAY;KACnC,EACD,MAAM,CACP,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,0BAA0B,CACvC,OAAgC,EAChC,MAAuB;IAEvB,0DAA0D;IAC1D,iEAAiE;IACjE,MAAM,EAAE,oBAAoB,EAAE,GAAG,OAAO,CAAC,yCAAyC,CAAC,CAAC;IAEpF,MAAM,KAAK,GAAG,IAAI,oBAAoB,CACpC;QACE,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,cAAc;QAC9E,YAAY,EAAE,OAAO,CAAC,YAAY;KACnC,EACD,MAAM,CACP,CAAC;IAEF,4BAA4B;IAC5B,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;IAEtB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,sBAAsB,CAAC,OAAqB,EAAE,MAAuB;IACnF,IAAI,IAAA,kCAAkB,EAAC,OAAO,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,0FAA0F,CAAC,CAAC;IAC9G,CAAC;IAED,oCAAoC;IACpC,iEAAiE;IACjE,MAAM,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,qCAAqC,CAAC,CAAC;IAC7E,MAAM,YAAY,GAAG,IAAA,+BAAe,EAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,OAAgC,CAAC;IAE5F,OAAO,IAAI,iBAAiB,CAC1B;QACE,IAAI,EAAE,YAAY,CAAC,IAAI;QACvB,IAAI,EAAE,YAAY,CAAC,IAAI;QACvB,QAAQ,EAAE,YAAY,CAAC,QAAQ;QAC/B,EAAE,EAAE,YAAY,CAAC,EAAE;QACnB,GAAG,EAAE,YAAY,CAAC,GAAG;QACrB,SAAS,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,cAAc;QACxF,YAAY,EAAE,YAAY,CAAC,YAAY;KACxC,EACD,MAAM,CACP,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,iBAAiB,CAAC,OAAsB;IACtD,kEAAkE;IAClE,MAAM,YAAY,GAAG,OAA+B,CAAC;IACrD,OAAO,sBAAsB,CAAC,YAAY,CAAC,CAAC;AAC9C,CAAC","sourcesContent":["/**\n * Storage Factory\n *\n * Factory functions for creating store drivers and session stores\n * based on configuration. Supports both Redis and Vercel KV providers.\n */\n\nimport type { StoreDriver } from './store.types';\nimport type { SessionStore } from '../auth/session/transport-session.types';\nimport type { FrontMcpLogger } from '../common/interfaces/logger.interface';\nimport {\n type RedisOptions,\n type RedisProviderOptions,\n type VercelKvProviderOptions,\n type PubsubOptions,\n isRedisProvider,\n isVercelKvProvider,\n} from '../common/types/options/redis.options';\n\n/**\n * Create a store driver based on configuration\n *\n * @param options - Storage configuration (Redis or Vercel KV)\n * @returns A store driver instance (not connected)\n *\n * @example Redis\n * ```typescript\n * const driver = createStoreDriver({\n * provider: 'redis',\n * host: 'localhost',\n * port: 6379,\n * });\n * await driver.connect();\n * ```\n *\n * @example Vercel KV\n * ```typescript\n * const driver = createStoreDriver({\n * provider: 'vercel-kv',\n * // Uses KV_REST_API_URL and KV_REST_API_TOKEN env vars\n * });\n * await driver.connect();\n * ```\n */\nexport function createStoreDriver(options: RedisOptions): StoreDriver {\n if (isVercelKvProvider(options)) {\n return createVercelKvStoreDriver(options);\n }\n\n if (isRedisProvider(options)) {\n return createRedisStoreDriver(options);\n }\n\n // Fallback for legacy format without provider field\n return createRedisStoreDriver(options as RedisProviderOptions);\n}\n\n/**\n * Create a Redis store driver\n */\nfunction createRedisStoreDriver(options: RedisProviderOptions): StoreDriver {\n // Lazy import to avoid bundling ioredis when not used\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { ScopedRedisStore } = require('./adapters/store.redis.adapter');\n\n return new ScopedRedisStore({\n options: {\n host: options.host,\n port: options.port,\n password: options.password,\n db: options.db,\n tls: options.tls ? {} : undefined,\n keyPrefix: options.keyPrefix,\n },\n });\n}\n\n/**\n * Create a Vercel KV store driver\n */\nfunction createVercelKvStoreDriver(options: VercelKvProviderOptions): StoreDriver {\n // Lazy import to avoid bundling @vercel/kv when not used\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { ScopedVercelKvStore } = require('./adapters/store.vercel-kv.adapter');\n\n return new ScopedVercelKvStore({\n url: options.url,\n token: options.token,\n keyPrefix: options.keyPrefix,\n });\n}\n\n/**\n * Create a session store based on configuration\n *\n * @param options - Storage configuration (Redis or Vercel KV)\n * @param logger - Optional logger instance\n * @returns A session store instance\n *\n * @example Redis\n * ```typescript\n * const store = await createSessionStore({\n * provider: 'redis',\n * host: 'localhost',\n * port: 6379,\n * });\n * ```\n *\n * @example Vercel KV\n * ```typescript\n * const store = await createSessionStore({\n * provider: 'vercel-kv',\n * });\n * ```\n */\nexport async function createSessionStore(options: RedisOptions, logger?: FrontMcpLogger): Promise<SessionStore> {\n if (isVercelKvProvider(options)) {\n return createVercelKvSessionStore(options, logger);\n }\n\n if (isRedisProvider(options)) {\n return createRedisSessionStore(options, logger);\n }\n\n // Fallback for legacy format without provider field\n return createRedisSessionStore(options as RedisProviderOptions, logger);\n}\n\n/**\n * Create a Redis session store\n */\nasync function createRedisSessionStore(options: RedisProviderOptions, logger?: FrontMcpLogger): Promise<SessionStore> {\n // Lazy require to avoid bundling ioredis when not used\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { RedisSessionStore } = require('../auth/session/redis-session.store');\n\n return new RedisSessionStore(\n {\n host: options.host,\n port: options.port,\n password: options.password,\n db: options.db,\n tls: options.tls,\n keyPrefix: options.keyPrefix ? `${options.keyPrefix}session:` : 'mcp:session:',\n defaultTtlMs: options.defaultTtlMs,\n },\n logger,\n );\n}\n\n/**\n * Create a Vercel KV session store\n */\nasync function createVercelKvSessionStore(\n options: VercelKvProviderOptions,\n logger?: FrontMcpLogger,\n): Promise<SessionStore> {\n // Lazy require to avoid bundling @vercel/kv when not used\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { VercelKvSessionStore } = require('../auth/session/vercel-kv-session.store');\n\n const store = new VercelKvSessionStore(\n {\n url: options.url,\n token: options.token,\n keyPrefix: options.keyPrefix ? `${options.keyPrefix}session:` : 'mcp:session:',\n defaultTtlMs: options.defaultTtlMs,\n },\n logger,\n );\n\n // Pre-connect for Vercel KV\n await store.connect();\n\n return store;\n}\n\n/**\n * Create a session store synchronously (for backwards compatibility)\n * Note: For Vercel KV, use createSessionStore() instead as it requires async connect\n *\n * @param options - Storage configuration (Redis only)\n * @param logger - Optional logger instance\n * @returns A session store instance\n */\nexport function createSessionStoreSync(options: RedisOptions, logger?: FrontMcpLogger): SessionStore {\n if (isVercelKvProvider(options)) {\n throw new Error('Vercel KV session store requires async initialization. Use createSessionStore() instead.');\n }\n\n // Redis only - synchronous creation\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { RedisSessionStore } = require('../auth/session/redis-session.store');\n const redisOptions = isRedisProvider(options) ? options : (options as RedisProviderOptions);\n\n return new RedisSessionStore(\n {\n host: redisOptions.host,\n port: redisOptions.port,\n password: redisOptions.password,\n db: redisOptions.db,\n tls: redisOptions.tls,\n keyPrefix: redisOptions.keyPrefix ? `${redisOptions.keyPrefix}session:` : 'mcp:session:',\n defaultTtlMs: redisOptions.defaultTtlMs,\n },\n logger,\n );\n}\n\n/**\n * Create a pub/sub store for resource subscriptions\n *\n * Pub/Sub requires Redis - Vercel KV does not support pub/sub operations.\n * Use this when you need resource subscriptions with Vercel KV for sessions.\n *\n * @param options - Pub/sub configuration (Redis only)\n * @returns A Redis store driver with pub/sub support\n *\n * @example Hybrid config\n * ```typescript\n * // Use Vercel KV for sessions, Redis for pub/sub\n * const sessionStore = await createSessionStore({ provider: 'vercel-kv' });\n * const pubsubStore = createPubsubStore({ host: 'localhost', port: 6379 });\n * ```\n */\nexport function createPubsubStore(options: PubsubOptions): StoreDriver {\n // PubsubOptions only allows Redis provider, so we can safely cast\n const redisOptions = options as RedisProviderOptions;\n return createRedisStoreDriver(redisOptions);\n}\n"]}
|
|
@@ -1,31 +1,32 @@
|
|
|
1
1
|
import { FlowBase, FlowRunOptions, ToolContext, ToolEntry } from '../../common';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';
|
|
4
|
+
import { type ToolResponseContent } from '@frontmcp/uipack/adapters';
|
|
4
5
|
declare const inputSchema: z.ZodObject<{
|
|
5
6
|
request: z.ZodObject<{
|
|
6
7
|
method: z.ZodLiteral<"tools/call">;
|
|
7
8
|
params: z.ZodObject<{
|
|
8
|
-
task: z.ZodOptional<z.ZodObject<{
|
|
9
|
-
ttl: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodNull]>>;
|
|
10
|
-
pollInterval: z.ZodOptional<z.ZodNumber>;
|
|
11
|
-
}, z.core.$loose>>;
|
|
12
9
|
_meta: z.ZodOptional<z.ZodObject<{
|
|
13
10
|
progressToken: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
14
11
|
"io.modelcontextprotocol/related-task": z.ZodOptional<z.ZodObject<{
|
|
15
12
|
taskId: z.ZodString;
|
|
16
|
-
}, z.core.$
|
|
13
|
+
}, z.core.$strip>>;
|
|
17
14
|
}, z.core.$loose>>;
|
|
15
|
+
task: z.ZodOptional<z.ZodObject<{
|
|
16
|
+
ttl: z.ZodOptional<z.ZodNumber>;
|
|
17
|
+
}, z.core.$strip>>;
|
|
18
18
|
name: z.ZodString;
|
|
19
19
|
arguments: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
20
|
-
}, z.core.$
|
|
20
|
+
}, z.core.$strip>;
|
|
21
21
|
}, z.core.$strip>;
|
|
22
22
|
ctx: z.ZodAny;
|
|
23
23
|
}, z.core.$strip>;
|
|
24
24
|
declare const outputSchema: z.ZodObject<{
|
|
25
25
|
_meta: z.ZodOptional<z.ZodObject<{
|
|
26
|
+
progressToken: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
26
27
|
"io.modelcontextprotocol/related-task": z.ZodOptional<z.ZodObject<{
|
|
27
28
|
taskId: z.ZodString;
|
|
28
|
-
}, z.core.$
|
|
29
|
+
}, z.core.$strip>>;
|
|
29
30
|
}, z.core.$loose>>;
|
|
30
31
|
content: z.ZodDefault<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
31
32
|
type: z.ZodLiteral<"text">;
|
|
@@ -82,6 +83,10 @@ declare const outputSchema: z.ZodObject<{
|
|
|
82
83
|
src: z.ZodString;
|
|
83
84
|
mimeType: z.ZodOptional<z.ZodString>;
|
|
84
85
|
sizes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
86
|
+
theme: z.ZodOptional<z.ZodEnum<{
|
|
87
|
+
light: "light";
|
|
88
|
+
dark: "dark";
|
|
89
|
+
}>>;
|
|
85
90
|
}, z.core.$strip>>>;
|
|
86
91
|
name: z.ZodString;
|
|
87
92
|
title: z.ZodOptional<z.ZodString>;
|
|
@@ -118,22 +123,15 @@ declare const stateSchema: z.ZodObject<{
|
|
|
118
123
|
arguments: z.ZodOptional<z.ZodObject<{}, z.core.$loose>>;
|
|
119
124
|
}, z.core.$loose>;
|
|
120
125
|
authInfo: z.ZodType<AuthInfo>;
|
|
121
|
-
tool: z.ZodCustom<ToolEntry<
|
|
122
|
-
|
|
123
|
-
}>, import("../../common").ToolOutputType, unknown, unknown>, ToolEntry<Readonly<{
|
|
124
|
-
[k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
|
|
125
|
-
}>, import("../../common").ToolOutputType, unknown, unknown>>;
|
|
126
|
-
toolContext: z.ZodCustom<ToolContext<Readonly<{
|
|
127
|
-
[k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
|
|
128
|
-
}>, import("../../common").ToolOutputType, unknown, unknown>, ToolContext<Readonly<{
|
|
129
|
-
[k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
|
|
130
|
-
}>, import("../../common").ToolOutputType, unknown, unknown>>;
|
|
126
|
+
tool: z.ZodCustom<ToolEntry<import("../../common").ToolInputType, import("../../common").ToolOutputType, unknown, unknown>, ToolEntry<import("../../common").ToolInputType, import("../../common").ToolOutputType, unknown, unknown>>;
|
|
127
|
+
toolContext: z.ZodCustom<ToolContext<import("../../common").ToolInputType, import("../../common").ToolOutputType, unknown, unknown>, ToolContext<import("../../common").ToolInputType, import("../../common").ToolOutputType, unknown, unknown>>;
|
|
131
128
|
rawOutput: z.ZodOptional<z.ZodAny>;
|
|
132
129
|
output: z.ZodObject<{
|
|
133
130
|
_meta: z.ZodOptional<z.ZodObject<{
|
|
131
|
+
progressToken: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
134
132
|
"io.modelcontextprotocol/related-task": z.ZodOptional<z.ZodObject<{
|
|
135
133
|
taskId: z.ZodString;
|
|
136
|
-
}, z.core.$
|
|
134
|
+
}, z.core.$strip>>;
|
|
137
135
|
}, z.core.$loose>>;
|
|
138
136
|
content: z.ZodDefault<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
139
137
|
type: z.ZodLiteral<"text">;
|
|
@@ -190,6 +188,10 @@ declare const stateSchema: z.ZodObject<{
|
|
|
190
188
|
src: z.ZodString;
|
|
191
189
|
mimeType: z.ZodOptional<z.ZodString>;
|
|
192
190
|
sizes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
191
|
+
theme: z.ZodOptional<z.ZodEnum<{
|
|
192
|
+
light: "light";
|
|
193
|
+
dark: "dark";
|
|
194
|
+
}>>;
|
|
193
195
|
}, z.core.$strip>>>;
|
|
194
196
|
name: z.ZodString;
|
|
195
197
|
title: z.ZodOptional<z.ZodString>;
|
|
@@ -221,11 +223,13 @@ declare const stateSchema: z.ZodObject<{
|
|
|
221
223
|
isError: z.ZodOptional<z.ZodBoolean>;
|
|
222
224
|
}, z.core.$loose>;
|
|
223
225
|
_toolOwnerId: z.ZodOptional<z.ZodString>;
|
|
226
|
+
uiResult: z.ZodType<ToolResponseContent | undefined>;
|
|
227
|
+
uiMeta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
224
228
|
}, z.core.$strip>;
|
|
225
229
|
declare const plan: {
|
|
226
230
|
readonly pre: ["parseInput", "findTool", "checkToolAuthorization", "createToolCallContext", "acquireQuota", "acquireSemaphore"];
|
|
227
231
|
readonly execute: ["validateInput", "execute", "validateOutput"];
|
|
228
|
-
readonly finalize: ["releaseSemaphore", "releaseQuota", "finalize"];
|
|
232
|
+
readonly finalize: ["releaseSemaphore", "releaseQuota", "applyUI", "finalize"];
|
|
229
233
|
};
|
|
230
234
|
declare global {
|
|
231
235
|
interface ExtendFlows {
|
|
@@ -255,6 +259,21 @@ export default class CallToolFlow extends FlowBase<typeof name> {
|
|
|
255
259
|
validateOutput(): Promise<void>;
|
|
256
260
|
releaseSemaphore(): Promise<void>;
|
|
257
261
|
releaseQuota(): Promise<void>;
|
|
262
|
+
/**
|
|
263
|
+
* Apply UI rendering to the tool response.
|
|
264
|
+
* This stage handles all UI-related logic including platform detection,
|
|
265
|
+
* serving mode resolution, and content formatting.
|
|
266
|
+
*/
|
|
267
|
+
applyUI(): Promise<void>;
|
|
268
|
+
/**
|
|
269
|
+
* Finalize the tool response.
|
|
270
|
+
* Validates output, applies UI result from applyUI stage, and sends the response.
|
|
271
|
+
*
|
|
272
|
+
* Note: This stage runs even when execute fails (as part of cleanup).
|
|
273
|
+
* If rawOutput is undefined, it means an error occurred during execution
|
|
274
|
+
* and the error will be propagated by the flow framework - we should not
|
|
275
|
+
* throw a new error here.
|
|
276
|
+
*/
|
|
258
277
|
finalize(): Promise<void>;
|
|
259
278
|
}
|
|
260
279
|
export {};
|