@decocms/runtime 0.28.1 → 1.0.0-alpha-candy.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/package.json +11 -77
- package/scripts/generate-json-schema.ts +24 -0
- package/src/asset-server/dev-server-proxy.ts +16 -0
- package/src/asset-server/index.ts +44 -0
- package/src/bindings/README.md +1 -1
- package/src/bindings/binder.ts +2 -5
- package/src/bindings/channels.ts +1 -1
- package/src/bindings/index.ts +0 -33
- package/src/bindings/language-model/utils.ts +0 -91
- package/src/bindings.ts +30 -108
- package/src/client.ts +1 -145
- package/src/index.ts +46 -175
- package/src/mcp.ts +8 -165
- package/src/proxy.ts +3 -62
- package/src/state.ts +1 -30
- package/src/tools.ts +336 -0
- package/src/wrangler.ts +5 -5
- package/tsconfig.json +8 -0
- package/dist/admin.d.ts +0 -5
- package/dist/admin.js +0 -21
- package/dist/admin.js.map +0 -1
- package/dist/bindings/deconfig/index.d.ts +0 -12
- package/dist/bindings/deconfig/index.js +0 -10
- package/dist/bindings/deconfig/index.js.map +0 -1
- package/dist/bindings/index.d.ts +0 -2315
- package/dist/bindings/index.js +0 -156
- package/dist/bindings/index.js.map +0 -1
- package/dist/chunk-3AWMDSOH.js +0 -96
- package/dist/chunk-3AWMDSOH.js.map +0 -1
- package/dist/chunk-4XSQKJLU.js +0 -105
- package/dist/chunk-4XSQKJLU.js.map +0 -1
- package/dist/chunk-5EYZ2LVM.js +0 -158
- package/dist/chunk-5EYZ2LVM.js.map +0 -1
- package/dist/chunk-7ITSLORK.js +0 -128
- package/dist/chunk-7ITSLORK.js.map +0 -1
- package/dist/chunk-I7BWSAN6.js +0 -49
- package/dist/chunk-I7BWSAN6.js.map +0 -1
- package/dist/chunk-L4OT2YDO.js +0 -27
- package/dist/chunk-L4OT2YDO.js.map +0 -1
- package/dist/chunk-SHQSNOFL.js +0 -769
- package/dist/chunk-SHQSNOFL.js.map +0 -1
- package/dist/chunk-UHR3BLMF.js +0 -92
- package/dist/chunk-UHR3BLMF.js.map +0 -1
- package/dist/chunk-UIJGM3NV.js +0 -518
- package/dist/chunk-UIJGM3NV.js.map +0 -1
- package/dist/chunk-ZPUT6RN6.js +0 -32
- package/dist/chunk-ZPUT6RN6.js.map +0 -1
- package/dist/client.d.ts +0 -28
- package/dist/client.js +0 -5
- package/dist/client.js.map +0 -1
- package/dist/d1-store.d.ts +0 -9
- package/dist/d1-store.js +0 -4
- package/dist/d1-store.js.map +0 -1
- package/dist/drizzle.d.ts +0 -49
- package/dist/drizzle.js +0 -121
- package/dist/drizzle.js.map +0 -1
- package/dist/index-LOfgE9a_.d.ts +0 -471
- package/dist/index-xKtm7A7B.d.ts +0 -530
- package/dist/index.d.ts +0 -10
- package/dist/index.js +0 -637
- package/dist/index.js.map +0 -1
- package/dist/mastra.d.ts +0 -10
- package/dist/mastra.js +0 -6
- package/dist/mastra.js.map +0 -1
- package/dist/mcp-87iLaW9V.d.ts +0 -105
- package/dist/mcp-client.d.ts +0 -232
- package/dist/mcp-client.js +0 -4
- package/dist/mcp-client.js.map +0 -1
- package/dist/proxy.d.ts +0 -11
- package/dist/proxy.js +0 -5
- package/dist/proxy.js.map +0 -1
- package/dist/resources.d.ts +0 -362
- package/dist/resources.js +0 -4
- package/dist/resources.js.map +0 -1
- package/dist/views.d.ts +0 -72
- package/dist/views.js +0 -4
- package/dist/views.js.map +0 -1
- package/src/admin.ts +0 -16
- package/src/auth.ts +0 -233
- package/src/bindings/deconfig/helpers.ts +0 -107
- package/src/bindings/deconfig/index.ts +0 -1
- package/src/bindings/deconfig/resources.ts +0 -659
- package/src/bindings/deconfig/types.ts +0 -106
- package/src/bindings/language-model/ai-sdk.ts +0 -87
- package/src/bindings/language-model/index.ts +0 -4
- package/src/bindings/resources/bindings.ts +0 -99
- package/src/bindings/resources/helpers.ts +0 -95
- package/src/bindings/resources/schemas.ts +0 -265
- package/src/bindings/views.ts +0 -14
- package/src/cf-imports.ts +0 -1
- package/src/d1-store.ts +0 -34
- package/src/deprecated.ts +0 -59
- package/src/drizzle.ts +0 -201
- package/src/mastra.ts +0 -898
- package/src/resources.ts +0 -168
- package/src/views.ts +0 -26
- package/src/workflow.ts +0 -193
package/package.json
CHANGED
|
@@ -1,101 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decocms/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-alpha-candy.1",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"scripts": {
|
|
6
|
-
"build": "tsup",
|
|
7
|
-
"prepublishOnly": "npm run build"
|
|
8
|
-
},
|
|
9
5
|
"dependencies": {
|
|
10
6
|
"@cloudflare/workers-types": "^4.20250617.0",
|
|
11
7
|
"@deco/mcp": "npm:@jsr/deco__mcp@0.5.5",
|
|
12
8
|
"@decocms/bindings": "*",
|
|
13
|
-
"@mastra/cloudflare-d1": "^0.13.4",
|
|
14
9
|
"@mastra/core": "^0.20.2",
|
|
15
10
|
"@modelcontextprotocol/sdk": "^1.19.1",
|
|
16
11
|
"@ai-sdk/provider": "^2.0.0",
|
|
17
12
|
"bidc": "0.0.3",
|
|
18
13
|
"drizzle-orm": "^0.44.5",
|
|
14
|
+
"hono": "^4.10.7",
|
|
19
15
|
"jose": "^6.0.11",
|
|
20
16
|
"mime-db": "1.52.0",
|
|
21
17
|
"zod": "^3.25.76",
|
|
22
18
|
"zod-from-json-schema": "^0.0.5",
|
|
23
19
|
"zod-to-json-schema": "3.25.0"
|
|
24
20
|
},
|
|
25
|
-
"main": "./dist/index.js",
|
|
26
|
-
"types": "./dist/index.d.ts",
|
|
27
|
-
"files": [
|
|
28
|
-
"dist/**/*",
|
|
29
|
-
"src/**/*",
|
|
30
|
-
"config-schema.json"
|
|
31
|
-
],
|
|
32
21
|
"exports": {
|
|
33
|
-
".":
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"./
|
|
39
|
-
|
|
40
|
-
"types": "./dist/proxy.d.ts",
|
|
41
|
-
"default": "./dist/proxy.js"
|
|
42
|
-
},
|
|
43
|
-
"./admin": {
|
|
44
|
-
"source": "./src/admin.ts",
|
|
45
|
-
"types": "./dist/admin.d.ts",
|
|
46
|
-
"default": "./dist/admin.js"
|
|
47
|
-
},
|
|
48
|
-
"./client": {
|
|
49
|
-
"source": "./src/client.ts",
|
|
50
|
-
"types": "./dist/client.d.ts",
|
|
51
|
-
"default": "./dist/client.js"
|
|
52
|
-
},
|
|
53
|
-
"./mastra": {
|
|
54
|
-
"source": "./src/mastra.ts",
|
|
55
|
-
"types": "./dist/mastra.d.ts",
|
|
56
|
-
"default": "./dist/mastra.js"
|
|
57
|
-
},
|
|
58
|
-
"./drizzle": {
|
|
59
|
-
"source": "./src/drizzle.ts",
|
|
60
|
-
"types": "./dist/drizzle.d.ts",
|
|
61
|
-
"default": "./dist/drizzle.js"
|
|
62
|
-
},
|
|
63
|
-
"./d1": {
|
|
64
|
-
"source": "./src/d1-store.ts",
|
|
65
|
-
"types": "./dist/d1-store.d.ts",
|
|
66
|
-
"default": "./dist/d1-store.js"
|
|
67
|
-
},
|
|
68
|
-
"./resources": {
|
|
69
|
-
"source": "./src/resources.ts",
|
|
70
|
-
"types": "./dist/resources.d.ts",
|
|
71
|
-
"default": "./dist/resources.js"
|
|
72
|
-
},
|
|
73
|
-
"./views": {
|
|
74
|
-
"source": "./src/views.ts",
|
|
75
|
-
"types": "./dist/views.d.ts",
|
|
76
|
-
"default": "./dist/views.js"
|
|
77
|
-
},
|
|
78
|
-
"./mcp-client": {
|
|
79
|
-
"source": "./src/mcp-client.ts",
|
|
80
|
-
"types": "./dist/mcp-client.d.ts",
|
|
81
|
-
"default": "./dist/mcp-client.js"
|
|
82
|
-
},
|
|
83
|
-
"./bindings": {
|
|
84
|
-
"source": "./src/bindings/index.ts",
|
|
85
|
-
"types": "./dist/bindings/index.d.ts",
|
|
86
|
-
"default": "./dist/bindings/index.js"
|
|
87
|
-
},
|
|
88
|
-
"./deconfig": {
|
|
89
|
-
"source": "./src/bindings/deconfig/index.ts",
|
|
90
|
-
"types": "./dist/bindings/deconfig/index.d.ts",
|
|
91
|
-
"default": "./dist/bindings/deconfig/index.js"
|
|
92
|
-
}
|
|
22
|
+
".": "./src/index.ts",
|
|
23
|
+
"./proxy": "./src/proxy.ts",
|
|
24
|
+
"./client": "./src/client.ts",
|
|
25
|
+
"./mcp-client": "./src/mcp-client.ts",
|
|
26
|
+
"./bindings": "./src/bindings/index.ts",
|
|
27
|
+
"./asset-server": "./src/asset-server/index.ts",
|
|
28
|
+
"./tools": "./src/tools.ts"
|
|
93
29
|
},
|
|
94
30
|
"devDependencies": {
|
|
95
31
|
"@types/mime-db": "^1.43.6",
|
|
96
|
-
"ts-json-schema-generator": "^2.4.0"
|
|
97
|
-
"tsup": "^8.5.0",
|
|
98
|
-
"typescript": "^5.9.3"
|
|
32
|
+
"ts-json-schema-generator": "^2.4.0"
|
|
99
33
|
},
|
|
100
34
|
"engines": {
|
|
101
35
|
"node": ">=24.0.0"
|
|
@@ -103,4 +37,4 @@
|
|
|
103
37
|
"publishConfig": {
|
|
104
38
|
"access": "public"
|
|
105
39
|
}
|
|
106
|
-
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// heavily inspired by https://github.com/cloudflare/workers-sdk/blob/main/packages/wrangler/scripts/generate-json-schema.ts
|
|
2
|
+
import { writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { createGenerator } from "ts-json-schema-generator";
|
|
5
|
+
import type { Config, Schema } from "ts-json-schema-generator";
|
|
6
|
+
|
|
7
|
+
const config: Config = {
|
|
8
|
+
path: join(import.meta.dirname!, "../src/wrangler.ts"),
|
|
9
|
+
type: "WranglerConfig",
|
|
10
|
+
skipTypeCheck: true,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const applyFormattingRules = (schema: Schema) => {
|
|
14
|
+
return { ...schema, allowTrailingCommas: true };
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const schema = applyFormattingRules(
|
|
18
|
+
createGenerator(config).createSchema(config.type),
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
writeFileSync(
|
|
22
|
+
join(import.meta.dirname!, "../config-schema.json"),
|
|
23
|
+
JSON.stringify(schema, null, 2),
|
|
24
|
+
);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { proxy } from "hono/proxy";
|
|
2
|
+
import { Context } from "hono";
|
|
3
|
+
|
|
4
|
+
export const devServerProxy = (url: string | URL) => (c: Context) => {
|
|
5
|
+
const incomingUrl = new URL(c.req.raw.url);
|
|
6
|
+
const target = new URL(url);
|
|
7
|
+
target.pathname = incomingUrl.pathname;
|
|
8
|
+
target.search = incomingUrl.search;
|
|
9
|
+
|
|
10
|
+
return proxy(target, {
|
|
11
|
+
raw: c.req.raw,
|
|
12
|
+
headers: {
|
|
13
|
+
...c.req.raw.headers,
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { serveStatic } from "hono/bun";
|
|
2
|
+
import { Hono } from "hono";
|
|
3
|
+
import { devServerProxy } from "./dev-server-proxy";
|
|
4
|
+
import { Handler } from "hono/types";
|
|
5
|
+
|
|
6
|
+
interface AssetServerConfig {
|
|
7
|
+
env: "development" | "production" | "test";
|
|
8
|
+
localDevProxyUrl?: string | URL;
|
|
9
|
+
assetsDirectory?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const DEFAULT_LOCAL_DEV_PROXY_URL = "http://localhost:4000";
|
|
13
|
+
const DEFAULT_ASSETS_DIRECTORY = "./dist/client";
|
|
14
|
+
|
|
15
|
+
interface HonoApp {
|
|
16
|
+
use: (path: string, handler: Handler) => void;
|
|
17
|
+
get: (path: string, handler: Handler) => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const applyAssetServerRoutes = (
|
|
21
|
+
app: HonoApp,
|
|
22
|
+
config: AssetServerConfig,
|
|
23
|
+
) => {
|
|
24
|
+
const environment = config.env;
|
|
25
|
+
const localDevProxyUrl =
|
|
26
|
+
config.localDevProxyUrl ?? DEFAULT_LOCAL_DEV_PROXY_URL;
|
|
27
|
+
const assetsDirectory = config.assetsDirectory ?? DEFAULT_ASSETS_DIRECTORY;
|
|
28
|
+
|
|
29
|
+
if (environment === "development") {
|
|
30
|
+
app.use("*", devServerProxy(localDevProxyUrl));
|
|
31
|
+
} else if (environment === "production") {
|
|
32
|
+
app.use("/assets/*", serveStatic({ root: assetsDirectory }));
|
|
33
|
+
app.get("*", serveStatic({ path: `${assetsDirectory}/index.html` }));
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const createAssetServer = (config: AssetServerConfig) => {
|
|
38
|
+
const app = new Hono();
|
|
39
|
+
applyAssetServerRoutes(app, config);
|
|
40
|
+
return app;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const createAssetServerFetcher = (config: AssetServerConfig) =>
|
|
44
|
+
createAssetServer(config).fetch;
|
package/src/bindings/README.md
CHANGED
package/src/bindings/binder.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
/* oxlint-disable no-explicit-any */
|
|
2
|
-
import { z } from "zod
|
|
2
|
+
import { z } from "zod";
|
|
3
3
|
import type { MCPConnection } from "../connection.ts";
|
|
4
|
-
import { createPrivateTool, createStreamableTool } from "../mastra.ts";
|
|
5
4
|
import {
|
|
6
5
|
createMCPFetchStub,
|
|
7
6
|
type MCPClientFetchStub,
|
|
8
7
|
type ToolBinder,
|
|
9
8
|
} from "../mcp.ts";
|
|
9
|
+
import { createPrivateTool, createStreamableTool } from "../tools.ts";
|
|
10
10
|
import { CHANNEL_BINDING } from "./channels.ts";
|
|
11
|
-
import { VIEW_BINDING } from "./views.ts";
|
|
12
11
|
|
|
13
12
|
// ToolLike is a simplified version of the Tool interface that matches what we need for bindings
|
|
14
13
|
export interface ToolLike<
|
|
@@ -93,8 +92,6 @@ export type MCPBindingClient<T extends ReturnType<typeof bindingClient>> =
|
|
|
93
92
|
ReturnType<T["forConnection"]>;
|
|
94
93
|
|
|
95
94
|
export const ChannelBinding = bindingClient(CHANNEL_BINDING);
|
|
96
|
-
export const ViewBinding = bindingClient(VIEW_BINDING);
|
|
97
|
-
|
|
98
95
|
export type { Callbacks } from "./channels.ts";
|
|
99
96
|
|
|
100
97
|
export const impl = <TBinder extends Binder>(
|
package/src/bindings/channels.ts
CHANGED
package/src/bindings/index.ts
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import { CHANNEL_BINDING } from "./channels.ts";
|
|
2
|
-
import { VIEW_BINDING as VIEWS_BINDING } from "./views.ts";
|
|
3
2
|
|
|
4
3
|
// Import new Resources 2.0 bindings function
|
|
5
4
|
import { LANGUAGE_MODEL_BINDING } from "@decocms/bindings/llm";
|
|
6
|
-
import { createResourceBindings } from "./resources/bindings.ts";
|
|
7
5
|
|
|
8
6
|
// Export types and utilities from binder
|
|
9
7
|
export {
|
|
10
8
|
bindingClient,
|
|
11
9
|
ChannelBinding,
|
|
12
10
|
impl,
|
|
13
|
-
ViewBinding,
|
|
14
11
|
type Binder,
|
|
15
12
|
type BinderImplementation,
|
|
16
13
|
type MCPBindingClient,
|
|
@@ -23,40 +20,10 @@ export * from "./channels.ts";
|
|
|
23
20
|
// Export binding utilities
|
|
24
21
|
export * from "./utils.ts";
|
|
25
22
|
|
|
26
|
-
// Export views schemas
|
|
27
|
-
export * from "./views.ts";
|
|
28
|
-
|
|
29
|
-
// Re-export Resources bindings function for convenience
|
|
30
|
-
export { createResourceBindings };
|
|
31
|
-
|
|
32
|
-
// Export resources types and schemas
|
|
33
|
-
export * from "./resources/bindings.ts";
|
|
34
|
-
export * from "./resources/helpers.ts";
|
|
35
|
-
export * from "./resources/schemas.ts";
|
|
36
|
-
|
|
37
|
-
// Export deconfig helpers and types
|
|
38
|
-
export {
|
|
39
|
-
getMetadataString as deconfigGetMetadataString,
|
|
40
|
-
getMetadataValue as deconfigGetMetadataValue,
|
|
41
|
-
normalizeDirectory as deconfigNormalizeDirectory,
|
|
42
|
-
ResourcePath,
|
|
43
|
-
ResourceUri,
|
|
44
|
-
} from "./deconfig/helpers.ts";
|
|
45
|
-
export { createDeconfigResource } from "./deconfig/index.ts";
|
|
46
|
-
export type {
|
|
47
|
-
DeconfigClient,
|
|
48
|
-
DeconfigResourceOptions,
|
|
49
|
-
EnhancedResourcesTools,
|
|
50
|
-
ResourcesBinding,
|
|
51
|
-
ResourcesTools,
|
|
52
|
-
} from "./deconfig/index.ts";
|
|
53
|
-
export { deconfigTools } from "./deconfig/types.ts";
|
|
54
|
-
|
|
55
23
|
export { streamToResponse } from "./language-model/utils.ts";
|
|
56
24
|
|
|
57
25
|
export const WellKnownBindings = {
|
|
58
26
|
Channel: CHANNEL_BINDING,
|
|
59
|
-
View: VIEWS_BINDING,
|
|
60
27
|
LanguageModel: LANGUAGE_MODEL_BINDING,
|
|
61
28
|
// Note: Resources is not included here since it's a generic function
|
|
62
29
|
// Use createResourceBindings(dataSchema) directly for Resources 2.0
|
|
@@ -25,94 +25,3 @@ export function streamToResponse(
|
|
|
25
25
|
},
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
export function responseToStream(
|
|
30
|
-
response: Response,
|
|
31
|
-
): ReadableStream<LanguageModelV2StreamPart> {
|
|
32
|
-
if (!response.body) {
|
|
33
|
-
throw new Error("Response body is null");
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return response.body.pipeThrough(new TextDecoderStream()).pipeThrough(
|
|
37
|
-
new TransformStream<string, LanguageModelV2StreamPart>({
|
|
38
|
-
transform(chunk, controller) {
|
|
39
|
-
// Split by newlines and parse each line
|
|
40
|
-
const lines = chunk.split("\n");
|
|
41
|
-
|
|
42
|
-
for (const line of lines) {
|
|
43
|
-
if (line.trim()) {
|
|
44
|
-
try {
|
|
45
|
-
const parsed = JSON.parse(line) as LanguageModelV2StreamPart;
|
|
46
|
-
controller.enqueue(parsed);
|
|
47
|
-
} catch (error) {
|
|
48
|
-
console.error("Failed to parse stream chunk:", error);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
}),
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Lazy promise wrapper that defers execution until the promise is awaited.
|
|
59
|
-
* The factory function is only called when .then() is invoked for the first time.
|
|
60
|
-
*/
|
|
61
|
-
class Lazy<T> implements PromiseLike<T> {
|
|
62
|
-
private promise: Promise<T> | null = null;
|
|
63
|
-
|
|
64
|
-
constructor(private factory: () => Promise<T>) {}
|
|
65
|
-
|
|
66
|
-
private getOrCreatePromise(): Promise<T> {
|
|
67
|
-
if (!this.promise) {
|
|
68
|
-
this.promise = this.factory();
|
|
69
|
-
}
|
|
70
|
-
return this.promise;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// eslint-disable-next-line no-thenable
|
|
74
|
-
then<TResult1 = T, TResult2 = never>(
|
|
75
|
-
onfulfilled?:
|
|
76
|
-
| ((value: T) => TResult1 | PromiseLike<TResult1>)
|
|
77
|
-
| null
|
|
78
|
-
| undefined,
|
|
79
|
-
onrejected?:
|
|
80
|
-
| ((reason: unknown) => TResult2 | PromiseLike<TResult2>)
|
|
81
|
-
| null
|
|
82
|
-
| undefined,
|
|
83
|
-
): PromiseLike<TResult1 | TResult2> {
|
|
84
|
-
return this.getOrCreatePromise().then(onfulfilled, onrejected);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
catch<TResult = never>(
|
|
88
|
-
onrejected?:
|
|
89
|
-
| ((reason: unknown) => TResult | PromiseLike<TResult>)
|
|
90
|
-
| null
|
|
91
|
-
| undefined,
|
|
92
|
-
): Promise<T | TResult> {
|
|
93
|
-
return this.getOrCreatePromise().catch(onrejected);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
finally(onfinally?: (() => void) | null | undefined): Promise<T> {
|
|
97
|
-
return this.getOrCreatePromise().finally(onfinally);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Creates a lazy promise that only executes when awaited.
|
|
103
|
-
*
|
|
104
|
-
* @param factory - A function that returns a Promise<T>
|
|
105
|
-
* @returns A Promise-like object that defers execution until .then() is called
|
|
106
|
-
*
|
|
107
|
-
* @example
|
|
108
|
-
* ```ts
|
|
109
|
-
* const lazyData = lazy(() => fetchExpensiveData());
|
|
110
|
-
* // fetchExpensiveData() is NOT called yet
|
|
111
|
-
*
|
|
112
|
-
* const result = await lazyData;
|
|
113
|
-
* // fetchExpensiveData() is called NOW
|
|
114
|
-
* ```
|
|
115
|
-
*/
|
|
116
|
-
export function lazy<T>(factory: () => Promise<T>): Promise<T> {
|
|
117
|
-
return new Lazy(factory) as unknown as Promise<T>;
|
|
118
|
-
}
|
package/src/bindings.ts
CHANGED
|
@@ -4,88 +4,22 @@ import { MCPClient } from "./mcp.ts";
|
|
|
4
4
|
import type {
|
|
5
5
|
BindingBase,
|
|
6
6
|
ContractBinding,
|
|
7
|
+
MCPAppBinding,
|
|
7
8
|
MCPBinding,
|
|
8
|
-
MCPIntegrationNameBinding,
|
|
9
9
|
} from "./wrangler.ts";
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
integrationId: string;
|
|
13
|
-
workspace: string;
|
|
14
|
-
branch?: string;
|
|
15
|
-
decoCmsApiUrl?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const normalizeWorkspace = (workspace: string) => {
|
|
19
|
-
if (workspace.startsWith("/users")) {
|
|
20
|
-
return workspace;
|
|
21
|
-
}
|
|
22
|
-
if (workspace.startsWith("/shared")) {
|
|
23
|
-
return workspace;
|
|
24
|
-
}
|
|
25
|
-
if (workspace.includes("/")) {
|
|
26
|
-
return workspace;
|
|
27
|
-
}
|
|
28
|
-
return `/shared/${workspace}`;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Url: /apps/mcp?appName=$appName
|
|
33
|
-
*/
|
|
34
|
-
const createAppsUrl = ({
|
|
35
|
-
appName,
|
|
36
|
-
decoChatApiUrl,
|
|
37
|
-
}: {
|
|
38
|
-
appName: string;
|
|
39
|
-
decoChatApiUrl?: string;
|
|
40
|
-
}) =>
|
|
41
|
-
new URL(
|
|
42
|
-
`/apps/mcp?appName=${appName}`,
|
|
43
|
-
decoChatApiUrl ?? "https://api.decocms.com",
|
|
44
|
-
).href;
|
|
45
|
-
/**
|
|
46
|
-
* Url: /:workspace.root/:workspace.slug/:integrationId/mcp
|
|
47
|
-
*/
|
|
48
|
-
const createIntegrationsUrl = ({
|
|
49
|
-
integrationId,
|
|
50
|
-
workspace,
|
|
51
|
-
decoCmsApiUrl,
|
|
52
|
-
branch,
|
|
53
|
-
}: IntegrationContext) => {
|
|
54
|
-
const base = `${normalizeWorkspace(workspace)}/${integrationId}/mcp`;
|
|
55
|
-
const url = new URL(base, decoCmsApiUrl ?? "https://api.decocms.com");
|
|
56
|
-
branch && url.searchParams.set("branch", branch);
|
|
57
|
-
return url.href;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
type WorkspaceClientContext = Omit<
|
|
11
|
+
type ClientContext = Omit<
|
|
61
12
|
RequestContext,
|
|
62
13
|
"ensureAuthenticated" | "state" | "fetchIntegrationMetadata"
|
|
63
14
|
>;
|
|
64
|
-
export const workspaceClient = (
|
|
65
|
-
ctx: WorkspaceClientContext,
|
|
66
|
-
): ReturnType<(typeof MCPClient)["forWorkspace"]> => {
|
|
67
|
-
return MCPClient.forWorkspace(ctx.workspace, ctx.token);
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const mcpClientForAppName = (appName: string, decoChatApiUrl?: string) => {
|
|
71
|
-
const mcpConnection: MCPConnection = {
|
|
72
|
-
type: "HTTP",
|
|
73
|
-
url: createAppsUrl({
|
|
74
|
-
appName,
|
|
75
|
-
decoChatApiUrl,
|
|
76
|
-
}),
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
return MCPClient.forConnection(mcpConnection);
|
|
80
|
-
};
|
|
81
15
|
|
|
82
16
|
export const proxyConnectionForId = (
|
|
83
|
-
|
|
84
|
-
ctx: Omit<
|
|
17
|
+
connectionId: string,
|
|
18
|
+
ctx: Omit<ClientContext, "token"> & {
|
|
85
19
|
token?: string;
|
|
86
20
|
cookie?: string;
|
|
21
|
+
meshUrl: string;
|
|
87
22
|
},
|
|
88
|
-
decoChatApiUrl?: string,
|
|
89
23
|
appName?: string,
|
|
90
24
|
): MCPConnection => {
|
|
91
25
|
let headers: Record<string, string> | undefined = appName
|
|
@@ -97,55 +31,39 @@ export const proxyConnectionForId = (
|
|
|
97
31
|
}
|
|
98
32
|
return {
|
|
99
33
|
type: "HTTP",
|
|
100
|
-
url:
|
|
101
|
-
integrationId,
|
|
102
|
-
workspace: ctx.workspace,
|
|
103
|
-
decoCmsApiUrl: decoChatApiUrl,
|
|
104
|
-
branch: ctx.branch,
|
|
105
|
-
}),
|
|
34
|
+
url: new URL(`/mcp/${connectionId}`, ctx.meshUrl).href,
|
|
106
35
|
token: ctx.token,
|
|
107
36
|
headers,
|
|
108
37
|
};
|
|
109
38
|
};
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
ctx:
|
|
113
|
-
decoChatApiUrl?: string,
|
|
39
|
+
const mcpClientForConnectionId = (
|
|
40
|
+
connectionId: string,
|
|
41
|
+
ctx: ClientContext,
|
|
114
42
|
appName?: string,
|
|
115
43
|
) => {
|
|
116
|
-
const mcpConnection = proxyConnectionForId(
|
|
117
|
-
integrationId,
|
|
118
|
-
ctx,
|
|
119
|
-
decoChatApiUrl,
|
|
120
|
-
appName,
|
|
121
|
-
);
|
|
44
|
+
const mcpConnection = proxyConnectionForId(connectionId, ctx, appName);
|
|
122
45
|
|
|
123
46
|
// TODO(@igorbrasileiro): Switch this proxy to be a proxy that call MCP Client.toolCall from @modelcontextprotocol
|
|
124
47
|
return MCPClient.forConnection(mcpConnection);
|
|
125
48
|
};
|
|
126
49
|
|
|
127
50
|
function mcpClientFromState(
|
|
128
|
-
binding: BindingBase |
|
|
51
|
+
binding: BindingBase | MCPAppBinding,
|
|
129
52
|
env: DefaultEnv,
|
|
130
53
|
) {
|
|
131
|
-
const ctx = env.
|
|
54
|
+
const ctx = env.MESH_REQUEST_CONTEXT;
|
|
132
55
|
const bindingFromState = ctx?.state?.[binding.name];
|
|
133
|
-
const
|
|
56
|
+
const connectionId =
|
|
134
57
|
bindingFromState &&
|
|
135
58
|
typeof bindingFromState === "object" &&
|
|
136
59
|
"value" in bindingFromState
|
|
137
60
|
? bindingFromState.value
|
|
138
61
|
: undefined;
|
|
139
|
-
if (typeof
|
|
62
|
+
if (typeof connectionId !== "string" && "app_name" in binding) {
|
|
140
63
|
// in case of a binding to an app name, we need to use the new apps/mcp endpoint which will proxy the request to the app but without any token
|
|
141
|
-
|
|
64
|
+
throw new Error("Binding to an app name is not supported");
|
|
142
65
|
}
|
|
143
|
-
return
|
|
144
|
-
integrationId,
|
|
145
|
-
ctx,
|
|
146
|
-
env.DECO_API_URL,
|
|
147
|
-
env.DECO_APP_NAME,
|
|
148
|
-
);
|
|
66
|
+
return mcpClientForConnectionId(connectionId, ctx);
|
|
149
67
|
}
|
|
150
68
|
|
|
151
69
|
export const createContractBinding = (
|
|
@@ -159,20 +77,24 @@ export const createIntegrationBinding = (
|
|
|
159
77
|
binding: MCPBinding,
|
|
160
78
|
env: DefaultEnv,
|
|
161
79
|
) => {
|
|
162
|
-
const
|
|
163
|
-
"
|
|
164
|
-
if (!
|
|
80
|
+
const connectionId =
|
|
81
|
+
"connection_id" in binding ? binding.connection_id : undefined;
|
|
82
|
+
if (!connectionId) {
|
|
165
83
|
return mcpClientFromState(binding, env);
|
|
166
84
|
}
|
|
85
|
+
if (!env.MESH_RUNTIME_TOKEN) {
|
|
86
|
+
throw new Error("MESH_RUNTIME_TOKEN is required");
|
|
87
|
+
}
|
|
88
|
+
if (!env.MESH_URL) {
|
|
89
|
+
throw new Error("MESH_URL is required");
|
|
90
|
+
}
|
|
167
91
|
// bindings pointed to an specific integration id are binded using the app deployment workspace
|
|
168
|
-
return
|
|
169
|
-
|
|
92
|
+
return mcpClientForConnectionId(
|
|
93
|
+
connectionId,
|
|
170
94
|
{
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
branch: env.DECO_REQUEST_CONTEXT?.branch,
|
|
95
|
+
token: env.MESH_RUNTIME_TOKEN,
|
|
96
|
+
meshUrl: env.MESH_URL,
|
|
174
97
|
},
|
|
175
|
-
env.
|
|
176
|
-
env.DECO_APP_NAME,
|
|
98
|
+
env.MESH_APP_NAME,
|
|
177
99
|
);
|
|
178
100
|
};
|