@decocms/runtime 0.28.0 → 1.0.0-alpha.10
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/config-schema.json +553 -0
- package/package.json +16 -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 +1 -1
- package/src/bindings/channels.ts +1 -1
- package/src/bindings/deconfig/resources.ts +47 -17
- package/src/bindings/deconfig/types.ts +1 -1
- package/src/bindings/index.ts +2 -0
- package/src/bindings/language-model/utils.ts +0 -91
- package/src/bindings/resources/bindings.ts +1 -1
- package/src/bindings/resources/schemas.ts +1 -1
- package/src/bindings/views.ts +1 -1
- package/src/bindings.ts +8 -7
- package/src/index.ts +5 -20
- package/src/mastra.ts +1 -229
- package/src/mcp.ts +7 -11
- package/src/proxy.ts +0 -8
- package/src/resources.ts +1 -1
- package/src/state.ts +1 -1
- package/src/views.ts +1 -1
- 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 -2312
- package/dist/bindings/index.js +0 -135
- 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-B7U9jXW4.d.ts +0 -530
- package/dist/index-uCMd27hU.d.ts +0 -471
- 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-DYmQ2RQf.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/bindings/language-model/ai-sdk.ts +0 -87
- package/src/bindings/language-model/index.ts +0 -4
- package/src/cf-imports.ts +0 -1
- package/src/d1-store.ts +0 -34
- package/src/deprecated.ts +0 -59
- package/src/workflow.ts +0 -193
package/dist/index.js
DELETED
|
@@ -1,637 +0,0 @@
|
|
|
1
|
-
import { DeconfigResource, MCPClient } from './chunk-SHQSNOFL.js';
|
|
2
|
-
export { createMCPFetchStub } from './chunk-SHQSNOFL.js';
|
|
3
|
-
import './chunk-5EYZ2LVM.js';
|
|
4
|
-
import './chunk-3AWMDSOH.js';
|
|
5
|
-
import { DECO_MCP_CLIENT_HEADER } from './chunk-4XSQKJLU.js';
|
|
6
|
-
import './chunk-UHR3BLMF.js';
|
|
7
|
-
import { createMCPServer, State, isWorkflow } from './chunk-UIJGM3NV.js';
|
|
8
|
-
import './chunk-L4OT2YDO.js';
|
|
9
|
-
import { D1Store } from './chunk-ZPUT6RN6.js';
|
|
10
|
-
import './chunk-7ITSLORK.js';
|
|
11
|
-
import './chunk-I7BWSAN6.js';
|
|
12
|
-
import { decodeJwt, jwtVerify } from 'jose';
|
|
13
|
-
import { Mastra } from '@mastra/core';
|
|
14
|
-
import { RuntimeContext } from '@mastra/core/di';
|
|
15
|
-
import { DurableObject } from 'cloudflare:workers';
|
|
16
|
-
|
|
17
|
-
var DECO_APP_AUTH_COOKIE_NAME = "deco_page_auth";
|
|
18
|
-
var MAX_COOKIE_SIZE = 4e3;
|
|
19
|
-
var StateParser = {
|
|
20
|
-
parse: (state) => {
|
|
21
|
-
return JSON.parse(decodeURIComponent(atob(state)));
|
|
22
|
-
},
|
|
23
|
-
stringify: (state) => {
|
|
24
|
-
return btoa(encodeURIComponent(JSON.stringify(state)));
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
var chunkValue = (value) => {
|
|
28
|
-
if (value.length <= MAX_COOKIE_SIZE) {
|
|
29
|
-
return [value];
|
|
30
|
-
}
|
|
31
|
-
const chunks = [];
|
|
32
|
-
for (let i = 0; i < value.length; i += MAX_COOKIE_SIZE) {
|
|
33
|
-
chunks.push(value.slice(i, i + MAX_COOKIE_SIZE));
|
|
34
|
-
}
|
|
35
|
-
return chunks;
|
|
36
|
-
};
|
|
37
|
-
var reassembleChunkedCookies = (cookies, baseName) => {
|
|
38
|
-
if (cookies[baseName]) {
|
|
39
|
-
return cookies[baseName];
|
|
40
|
-
}
|
|
41
|
-
const chunks = [];
|
|
42
|
-
let index = 0;
|
|
43
|
-
while (true) {
|
|
44
|
-
const chunkName = `${baseName}_${index}`;
|
|
45
|
-
if (!cookies[chunkName]) {
|
|
46
|
-
break;
|
|
47
|
-
}
|
|
48
|
-
chunks.push(cookies[chunkName]);
|
|
49
|
-
index++;
|
|
50
|
-
}
|
|
51
|
-
return chunks.length > 0 ? chunks.join("") : void 0;
|
|
52
|
-
};
|
|
53
|
-
var parseCookies = (cookieHeader) => {
|
|
54
|
-
const cookies = {};
|
|
55
|
-
if (!cookieHeader) return cookies;
|
|
56
|
-
cookieHeader.split(";").forEach((cookie) => {
|
|
57
|
-
const [name, ...rest] = cookie.trim().split("=");
|
|
58
|
-
if (name && rest.length > 0) {
|
|
59
|
-
cookies[name] = decodeURIComponent(rest.join("="));
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
return cookies;
|
|
63
|
-
};
|
|
64
|
-
var parseJWK = (jwk) => JSON.parse(atob(jwk));
|
|
65
|
-
var getReqToken = async (req, env) => {
|
|
66
|
-
const token = () => {
|
|
67
|
-
const authHeader = req.headers.get("Authorization");
|
|
68
|
-
if (authHeader) {
|
|
69
|
-
return authHeader.split(" ")[1];
|
|
70
|
-
}
|
|
71
|
-
const cookieHeader = req.headers.get("Cookie");
|
|
72
|
-
if (cookieHeader) {
|
|
73
|
-
const cookies = parseCookies(cookieHeader);
|
|
74
|
-
return reassembleChunkedCookies(cookies, DECO_APP_AUTH_COOKIE_NAME);
|
|
75
|
-
}
|
|
76
|
-
return void 0;
|
|
77
|
-
};
|
|
78
|
-
const authToken = token();
|
|
79
|
-
if (!authToken) {
|
|
80
|
-
return void 0;
|
|
81
|
-
}
|
|
82
|
-
env.DECO_API_JWT_PUBLIC_KEY && await jwtVerify(authToken, parseJWK(env.DECO_API_JWT_PUBLIC_KEY), {
|
|
83
|
-
issuer: "https://api.decocms.com",
|
|
84
|
-
algorithms: ["RS256"],
|
|
85
|
-
typ: "JWT"
|
|
86
|
-
}).catch((err) => {
|
|
87
|
-
console.error(
|
|
88
|
-
`[auth-token]: error validating: ${err} ${env.DECO_API_JWT_PUBLIC_KEY}`
|
|
89
|
-
);
|
|
90
|
-
});
|
|
91
|
-
return authToken;
|
|
92
|
-
};
|
|
93
|
-
var handleAuthCallback = async (req, options) => {
|
|
94
|
-
const url = new URL(req.url);
|
|
95
|
-
const code = url.searchParams.get("code");
|
|
96
|
-
const state = url.searchParams.get("state");
|
|
97
|
-
if (!code) {
|
|
98
|
-
return new Response("Missing authorization code", { status: 400 });
|
|
99
|
-
}
|
|
100
|
-
let next = "/";
|
|
101
|
-
if (state) {
|
|
102
|
-
try {
|
|
103
|
-
const parsedState = StateParser.parse(state);
|
|
104
|
-
next = parsedState.next || "/";
|
|
105
|
-
} catch {
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
try {
|
|
109
|
-
const apiUrl = options.apiUrl ?? "https://api.decocms.com";
|
|
110
|
-
const exchangeResponse = await fetch(`${apiUrl}/apps/code-exchange`, {
|
|
111
|
-
method: "POST",
|
|
112
|
-
headers: {
|
|
113
|
-
"Content-Type": "application/json"
|
|
114
|
-
},
|
|
115
|
-
body: JSON.stringify({
|
|
116
|
-
code,
|
|
117
|
-
client_id: options.appName
|
|
118
|
-
})
|
|
119
|
-
});
|
|
120
|
-
if (!exchangeResponse.ok) {
|
|
121
|
-
console.error(
|
|
122
|
-
"authentication failed",
|
|
123
|
-
code,
|
|
124
|
-
options.appName,
|
|
125
|
-
await exchangeResponse.text().catch((_) => "")
|
|
126
|
-
);
|
|
127
|
-
return new Response("Authentication failed", { status: 401 });
|
|
128
|
-
}
|
|
129
|
-
const { access_token } = await exchangeResponse.json();
|
|
130
|
-
if (!access_token) {
|
|
131
|
-
return new Response("No access token received", { status: 401 });
|
|
132
|
-
}
|
|
133
|
-
const chunks = chunkValue(access_token);
|
|
134
|
-
const headers = new Headers();
|
|
135
|
-
headers.set("Location", next);
|
|
136
|
-
if (chunks.length === 1) {
|
|
137
|
-
headers.set(
|
|
138
|
-
"Set-Cookie",
|
|
139
|
-
`${DECO_APP_AUTH_COOKIE_NAME}=${access_token}; HttpOnly; SameSite=None; Secure; Path=/`
|
|
140
|
-
);
|
|
141
|
-
} else {
|
|
142
|
-
chunks.forEach((chunk, index) => {
|
|
143
|
-
headers.append(
|
|
144
|
-
"Set-Cookie",
|
|
145
|
-
`${DECO_APP_AUTH_COOKIE_NAME}_${index}=${chunk}; HttpOnly; SameSite=None; Secure; Path=/`
|
|
146
|
-
);
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
return new Response(null, {
|
|
150
|
-
status: 302,
|
|
151
|
-
headers
|
|
152
|
-
});
|
|
153
|
-
} catch (err) {
|
|
154
|
-
return new Response(`Authentication failed ${err}`, { status: 500 });
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
var removeAuthCookie = (headers) => {
|
|
158
|
-
headers.append(
|
|
159
|
-
"Set-Cookie",
|
|
160
|
-
`${DECO_APP_AUTH_COOKIE_NAME}=; HttpOnly; SameSite=None; Secure; Path=/; Max-Age=0`
|
|
161
|
-
);
|
|
162
|
-
for (let i = 0; i < 10; i++) {
|
|
163
|
-
headers.append(
|
|
164
|
-
"Set-Cookie",
|
|
165
|
-
`${DECO_APP_AUTH_COOKIE_NAME}_${i}=; HttpOnly; SameSite=None; Secure; Path=/; Max-Age=0`
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
var handleLogout = (req) => {
|
|
170
|
-
const url = new URL(req.url);
|
|
171
|
-
const next = url.searchParams.get("next");
|
|
172
|
-
const redirectTo = new URL("/", url);
|
|
173
|
-
const headers = new Headers();
|
|
174
|
-
removeAuthCookie(headers);
|
|
175
|
-
headers.set("Location", next ?? redirectTo.href);
|
|
176
|
-
return new Response(null, {
|
|
177
|
-
status: 302,
|
|
178
|
-
headers
|
|
179
|
-
});
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
// src/bindings.ts
|
|
183
|
-
var normalizeWorkspace = (workspace) => {
|
|
184
|
-
if (workspace.startsWith("/users")) {
|
|
185
|
-
return workspace;
|
|
186
|
-
}
|
|
187
|
-
if (workspace.startsWith("/shared")) {
|
|
188
|
-
return workspace;
|
|
189
|
-
}
|
|
190
|
-
if (workspace.includes("/")) {
|
|
191
|
-
return workspace;
|
|
192
|
-
}
|
|
193
|
-
return `/shared/${workspace}`;
|
|
194
|
-
};
|
|
195
|
-
var createAppsUrl = ({
|
|
196
|
-
appName,
|
|
197
|
-
decoChatApiUrl
|
|
198
|
-
}) => new URL(
|
|
199
|
-
`/apps/mcp?appName=${appName}`,
|
|
200
|
-
decoChatApiUrl ?? "https://api.decocms.com"
|
|
201
|
-
).href;
|
|
202
|
-
var createIntegrationsUrl = ({
|
|
203
|
-
integrationId,
|
|
204
|
-
workspace,
|
|
205
|
-
decoCmsApiUrl,
|
|
206
|
-
branch
|
|
207
|
-
}) => {
|
|
208
|
-
const base = `${normalizeWorkspace(workspace)}/${integrationId}/mcp`;
|
|
209
|
-
const url = new URL(base, decoCmsApiUrl ?? "https://api.decocms.com");
|
|
210
|
-
branch && url.searchParams.set("branch", branch);
|
|
211
|
-
return url.href;
|
|
212
|
-
};
|
|
213
|
-
var workspaceClient = (ctx) => {
|
|
214
|
-
return MCPClient.forWorkspace(ctx.workspace, ctx.token);
|
|
215
|
-
};
|
|
216
|
-
var mcpClientForAppName = (appName, decoChatApiUrl) => {
|
|
217
|
-
const mcpConnection = {
|
|
218
|
-
type: "HTTP",
|
|
219
|
-
url: createAppsUrl({
|
|
220
|
-
appName,
|
|
221
|
-
decoChatApiUrl
|
|
222
|
-
})
|
|
223
|
-
};
|
|
224
|
-
return MCPClient.forConnection(mcpConnection);
|
|
225
|
-
};
|
|
226
|
-
var proxyConnectionForId = (integrationId, ctx, decoChatApiUrl, appName) => {
|
|
227
|
-
let headers = appName ? { "x-caller-app": appName } : void 0;
|
|
228
|
-
if (ctx.cookie) {
|
|
229
|
-
headers ??= {};
|
|
230
|
-
headers.cookie = ctx.cookie;
|
|
231
|
-
}
|
|
232
|
-
return {
|
|
233
|
-
type: "HTTP",
|
|
234
|
-
url: createIntegrationsUrl({
|
|
235
|
-
integrationId,
|
|
236
|
-
workspace: ctx.workspace,
|
|
237
|
-
decoCmsApiUrl: decoChatApiUrl,
|
|
238
|
-
branch: ctx.branch
|
|
239
|
-
}),
|
|
240
|
-
token: ctx.token,
|
|
241
|
-
headers
|
|
242
|
-
};
|
|
243
|
-
};
|
|
244
|
-
var mcpClientForIntegrationId = (integrationId, ctx, decoChatApiUrl, appName) => {
|
|
245
|
-
const mcpConnection = proxyConnectionForId(
|
|
246
|
-
integrationId,
|
|
247
|
-
ctx,
|
|
248
|
-
decoChatApiUrl,
|
|
249
|
-
appName
|
|
250
|
-
);
|
|
251
|
-
return MCPClient.forConnection(mcpConnection);
|
|
252
|
-
};
|
|
253
|
-
function mcpClientFromState(binding, env) {
|
|
254
|
-
const ctx = env.DECO_REQUEST_CONTEXT;
|
|
255
|
-
const bindingFromState = ctx?.state?.[binding.name];
|
|
256
|
-
const integrationId = bindingFromState && typeof bindingFromState === "object" && "value" in bindingFromState ? bindingFromState.value : void 0;
|
|
257
|
-
if (typeof integrationId !== "string" && "integration_name" in binding) {
|
|
258
|
-
return mcpClientForAppName(binding.integration_name, env.DECO_API_URL);
|
|
259
|
-
}
|
|
260
|
-
return mcpClientForIntegrationId(
|
|
261
|
-
integrationId,
|
|
262
|
-
ctx,
|
|
263
|
-
env.DECO_API_URL,
|
|
264
|
-
env.DECO_APP_NAME
|
|
265
|
-
);
|
|
266
|
-
}
|
|
267
|
-
var createContractBinding = (binding, env) => {
|
|
268
|
-
return mcpClientFromState(binding, env);
|
|
269
|
-
};
|
|
270
|
-
var createIntegrationBinding = (binding, env) => {
|
|
271
|
-
const integrationId = "integration_id" in binding ? binding.integration_id : void 0;
|
|
272
|
-
if (!integrationId) {
|
|
273
|
-
return mcpClientFromState(binding, env);
|
|
274
|
-
}
|
|
275
|
-
return mcpClientForIntegrationId(
|
|
276
|
-
integrationId,
|
|
277
|
-
{
|
|
278
|
-
workspace: env.DECO_WORKSPACE,
|
|
279
|
-
token: env.DECO_API_TOKEN,
|
|
280
|
-
branch: env.DECO_REQUEST_CONTEXT?.branch
|
|
281
|
-
},
|
|
282
|
-
env.DECO_API_URL,
|
|
283
|
-
env.DECO_APP_NAME
|
|
284
|
-
);
|
|
285
|
-
};
|
|
286
|
-
|
|
287
|
-
// src/workflow.ts
|
|
288
|
-
var createRuntimeContext = (env, ctx) => {
|
|
289
|
-
const runtimeContext = new RuntimeContext();
|
|
290
|
-
runtimeContext.set("env", env);
|
|
291
|
-
runtimeContext.set("ctx", ctx);
|
|
292
|
-
return runtimeContext;
|
|
293
|
-
};
|
|
294
|
-
var Workflow = (server, workflows) => {
|
|
295
|
-
return class Workflow extends DurableObject {
|
|
296
|
-
constructor(ctx, env) {
|
|
297
|
-
super(ctx, env);
|
|
298
|
-
this.ctx = ctx;
|
|
299
|
-
this.env = env;
|
|
300
|
-
}
|
|
301
|
-
bindings(ctx) {
|
|
302
|
-
return withBindings({
|
|
303
|
-
env: this.env,
|
|
304
|
-
server,
|
|
305
|
-
tokenOrContext: ctx
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
runWithContext(ctx, f) {
|
|
309
|
-
const bindings = this.bindings(ctx);
|
|
310
|
-
return State.run(
|
|
311
|
-
{
|
|
312
|
-
ctx: {
|
|
313
|
-
waitUntil: this.ctx.waitUntil.bind(this.ctx)
|
|
314
|
-
},
|
|
315
|
-
env: this.bindings(ctx)
|
|
316
|
-
},
|
|
317
|
-
() => f(bindings)
|
|
318
|
-
);
|
|
319
|
-
}
|
|
320
|
-
async #getWorkflow(workflowId, bindings) {
|
|
321
|
-
const bindedWorkflows = await Promise.all(
|
|
322
|
-
workflows?.map(async (workflow) => {
|
|
323
|
-
const workflowResult = workflow(bindings);
|
|
324
|
-
if (isWorkflow(workflowResult)) {
|
|
325
|
-
return { workflow: workflowResult };
|
|
326
|
-
}
|
|
327
|
-
return await workflowResult;
|
|
328
|
-
}) ?? []
|
|
329
|
-
);
|
|
330
|
-
const workflowsMap = Object.fromEntries(
|
|
331
|
-
bindedWorkflows.map((w) => [w.workflow.id, w.workflow])
|
|
332
|
-
);
|
|
333
|
-
const d1Storage = new D1Store({
|
|
334
|
-
client: bindings.DECO_WORKSPACE_DB
|
|
335
|
-
});
|
|
336
|
-
const mastra = new Mastra({
|
|
337
|
-
storage: d1Storage,
|
|
338
|
-
workflows: {
|
|
339
|
-
[workflowId]: workflowsMap[workflowId]
|
|
340
|
-
},
|
|
341
|
-
telemetry: {
|
|
342
|
-
enabled: true,
|
|
343
|
-
serviceName: `app-${this.env.DECO_CHAT_SCRIPT_SLUG ?? this.env.DECO_APP_SLUG}`
|
|
344
|
-
}
|
|
345
|
-
});
|
|
346
|
-
return { workflow: mastra.getWorkflow(workflowId) };
|
|
347
|
-
}
|
|
348
|
-
start({ workflowId, runId, args, ctx }) {
|
|
349
|
-
return this.runWithContext(ctx, async (bindings) => {
|
|
350
|
-
const { workflow } = await this.#getWorkflow(workflowId, bindings);
|
|
351
|
-
const run = await workflow.createRunAsync({
|
|
352
|
-
runId: this.ctx.id.name ?? runId
|
|
353
|
-
});
|
|
354
|
-
const promise = run.start({
|
|
355
|
-
inputData: args,
|
|
356
|
-
runtimeContext: createRuntimeContext(bindings, this.ctx)
|
|
357
|
-
});
|
|
358
|
-
this.ctx.waitUntil(
|
|
359
|
-
promise.then(() => {
|
|
360
|
-
console.debug("workflow", run.runId, "finished successfully");
|
|
361
|
-
}).catch((e) => {
|
|
362
|
-
console.error("workflow", run.runId, "finished with error", e);
|
|
363
|
-
throw e;
|
|
364
|
-
})
|
|
365
|
-
);
|
|
366
|
-
return {
|
|
367
|
-
runId: run.runId
|
|
368
|
-
};
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
cancel({ workflowId, runId, ctx }) {
|
|
372
|
-
return this.runWithContext(ctx, async () => {
|
|
373
|
-
const { workflow } = await this.#getWorkflow(
|
|
374
|
-
workflowId,
|
|
375
|
-
this.bindings(ctx)
|
|
376
|
-
);
|
|
377
|
-
const run = await workflow.createRunAsync({
|
|
378
|
-
runId: this.ctx.id.name ?? runId
|
|
379
|
-
});
|
|
380
|
-
this.ctx.waitUntil(run.cancel());
|
|
381
|
-
return {
|
|
382
|
-
cancelled: true
|
|
383
|
-
};
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
resume({ workflowId, runId, resumeData, stepId, ctx }) {
|
|
387
|
-
return this.runWithContext(ctx, async (bindings) => {
|
|
388
|
-
const { workflow } = await this.#getWorkflow(workflowId, bindings);
|
|
389
|
-
const run = await workflow.createRunAsync({
|
|
390
|
-
runId: this.ctx.id.name ?? runId
|
|
391
|
-
});
|
|
392
|
-
this.ctx.waitUntil(
|
|
393
|
-
run.resume({
|
|
394
|
-
resumeData,
|
|
395
|
-
step: stepId,
|
|
396
|
-
runtimeContext: createRuntimeContext(bindings, this.ctx)
|
|
397
|
-
})
|
|
398
|
-
);
|
|
399
|
-
return {
|
|
400
|
-
resumed: true
|
|
401
|
-
};
|
|
402
|
-
});
|
|
403
|
-
}
|
|
404
|
-
};
|
|
405
|
-
};
|
|
406
|
-
|
|
407
|
-
// src/index.ts
|
|
408
|
-
var WorkersMCPBindings = {
|
|
409
|
-
parse: (bindings) => {
|
|
410
|
-
if (!bindings) return [];
|
|
411
|
-
try {
|
|
412
|
-
return JSON.parse(atob(bindings));
|
|
413
|
-
} catch {
|
|
414
|
-
return [];
|
|
415
|
-
}
|
|
416
|
-
},
|
|
417
|
-
stringify: (bindings) => {
|
|
418
|
-
return btoa(JSON.stringify(bindings));
|
|
419
|
-
}
|
|
420
|
-
};
|
|
421
|
-
var creatorByType = {
|
|
422
|
-
mcp: createIntegrationBinding,
|
|
423
|
-
contract: createContractBinding
|
|
424
|
-
};
|
|
425
|
-
var withDefaultBindings = ({
|
|
426
|
-
env,
|
|
427
|
-
server,
|
|
428
|
-
ctx,
|
|
429
|
-
url
|
|
430
|
-
}) => {
|
|
431
|
-
const client = workspaceClient(ctx);
|
|
432
|
-
const createWorkspaceDB = (ctx2) => {
|
|
433
|
-
const client2 = workspaceClient(ctx2);
|
|
434
|
-
return {
|
|
435
|
-
query: ({ sql, params }) => {
|
|
436
|
-
return client2.DATABASES_RUN_SQL({
|
|
437
|
-
sql,
|
|
438
|
-
params
|
|
439
|
-
});
|
|
440
|
-
}
|
|
441
|
-
};
|
|
442
|
-
};
|
|
443
|
-
env["SELF"] = new Proxy(
|
|
444
|
-
{},
|
|
445
|
-
{
|
|
446
|
-
get: (_, prop) => {
|
|
447
|
-
if (prop === "toJSON") {
|
|
448
|
-
return null;
|
|
449
|
-
}
|
|
450
|
-
return async (args) => {
|
|
451
|
-
return await server.callTool({
|
|
452
|
-
toolCallId: prop,
|
|
453
|
-
toolCallInput: args
|
|
454
|
-
});
|
|
455
|
-
};
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
);
|
|
459
|
-
const workspaceDbBinding = {
|
|
460
|
-
...createWorkspaceDB(ctx),
|
|
461
|
-
forContext: createWorkspaceDB
|
|
462
|
-
};
|
|
463
|
-
env["DECO_API"] = MCPClient;
|
|
464
|
-
env["DECO_WORKSPACE_API"] = client;
|
|
465
|
-
env["DECO_WORKSPACE_DB"] = workspaceDbBinding;
|
|
466
|
-
env["DECO_CHAT_API"] = MCPClient;
|
|
467
|
-
env["DECO_CHAT_WORKSPACE_API"] = client;
|
|
468
|
-
env["DECO_CHAT_WORKSPACE_DB"] = workspaceDbBinding;
|
|
469
|
-
env["IS_LOCAL"] = (url?.startsWith("http://localhost") || url?.startsWith("http://127.0.0.1")) ?? false;
|
|
470
|
-
};
|
|
471
|
-
var UnauthorizedError = class extends Error {
|
|
472
|
-
constructor(message, redirectTo) {
|
|
473
|
-
super(message);
|
|
474
|
-
this.redirectTo = redirectTo;
|
|
475
|
-
this.name = "UnauthorizedError";
|
|
476
|
-
}
|
|
477
|
-
};
|
|
478
|
-
var AUTH_CALLBACK_ENDPOINT = "/oauth/callback";
|
|
479
|
-
var AUTH_START_ENDPOINT = "/oauth/start";
|
|
480
|
-
var AUTH_LOGOUT_ENDPOINT = "/oauth/logout";
|
|
481
|
-
var AUTHENTICATED = (user, workspace) => () => {
|
|
482
|
-
return {
|
|
483
|
-
...user ?? {},
|
|
484
|
-
workspace
|
|
485
|
-
};
|
|
486
|
-
};
|
|
487
|
-
var withBindings = ({
|
|
488
|
-
env: _env,
|
|
489
|
-
server,
|
|
490
|
-
tokenOrContext,
|
|
491
|
-
origin,
|
|
492
|
-
url,
|
|
493
|
-
branch
|
|
494
|
-
}) => {
|
|
495
|
-
branch ??= void 0;
|
|
496
|
-
const env = _env;
|
|
497
|
-
const apiUrl = env.DECO_API_URL ?? "https://api.decocms.com";
|
|
498
|
-
let context;
|
|
499
|
-
if (typeof tokenOrContext === "string") {
|
|
500
|
-
const decoded = decodeJwt(tokenOrContext);
|
|
501
|
-
const workspace = decoded.aud;
|
|
502
|
-
context = {
|
|
503
|
-
state: decoded.state,
|
|
504
|
-
token: tokenOrContext,
|
|
505
|
-
integrationId: decoded.integrationId,
|
|
506
|
-
workspace,
|
|
507
|
-
ensureAuthenticated: AUTHENTICATED(decoded.user, workspace),
|
|
508
|
-
branch
|
|
509
|
-
};
|
|
510
|
-
} else if (typeof tokenOrContext === "object") {
|
|
511
|
-
context = tokenOrContext;
|
|
512
|
-
const decoded = decodeJwt(tokenOrContext.token);
|
|
513
|
-
const workspace = decoded.aud;
|
|
514
|
-
const appName = decoded.appName;
|
|
515
|
-
context.callerApp = appName;
|
|
516
|
-
context.integrationId ??= decoded.integrationId;
|
|
517
|
-
context.ensureAuthenticated = AUTHENTICATED(decoded.user, workspace);
|
|
518
|
-
} else {
|
|
519
|
-
context = {
|
|
520
|
-
state: void 0,
|
|
521
|
-
token: env.DECO_API_TOKEN,
|
|
522
|
-
workspace: env.DECO_WORKSPACE,
|
|
523
|
-
branch,
|
|
524
|
-
ensureAuthenticated: (options) => {
|
|
525
|
-
const workspaceHint = options?.workspaceHint ?? env.DECO_WORKSPACE;
|
|
526
|
-
const authUri = new URL("/apps/oauth", apiUrl);
|
|
527
|
-
authUri.searchParams.set("client_id", env.DECO_APP_NAME);
|
|
528
|
-
authUri.searchParams.set(
|
|
529
|
-
"redirect_uri",
|
|
530
|
-
new URL(AUTH_CALLBACK_ENDPOINT, origin ?? env.DECO_APP_ENTRYPOINT).href
|
|
531
|
-
);
|
|
532
|
-
workspaceHint && authUri.searchParams.set("workspace_hint", workspaceHint);
|
|
533
|
-
throw new UnauthorizedError("Unauthorized", authUri);
|
|
534
|
-
}
|
|
535
|
-
};
|
|
536
|
-
}
|
|
537
|
-
env.DECO_REQUEST_CONTEXT = context;
|
|
538
|
-
env.DECO_CHAT_REQUEST_CONTEXT = context;
|
|
539
|
-
const bindings = WorkersMCPBindings.parse(env.DECO_BINDINGS);
|
|
540
|
-
for (const binding of bindings) {
|
|
541
|
-
env[binding.name] = creatorByType[binding.type](binding, env);
|
|
542
|
-
}
|
|
543
|
-
withDefaultBindings({
|
|
544
|
-
env,
|
|
545
|
-
server,
|
|
546
|
-
ctx: env.DECO_REQUEST_CONTEXT,
|
|
547
|
-
url
|
|
548
|
-
});
|
|
549
|
-
return env;
|
|
550
|
-
};
|
|
551
|
-
var withRuntime = (userFns) => {
|
|
552
|
-
const server = createMCPServer(userFns);
|
|
553
|
-
const fetcher = async (req, env, ctx) => {
|
|
554
|
-
const url = new URL(req.url);
|
|
555
|
-
if (url.pathname === AUTH_CALLBACK_ENDPOINT) {
|
|
556
|
-
return handleAuthCallback(req, {
|
|
557
|
-
apiUrl: env.DECO_API_URL,
|
|
558
|
-
appName: env.DECO_APP_NAME
|
|
559
|
-
});
|
|
560
|
-
}
|
|
561
|
-
if (url.pathname === AUTH_START_ENDPOINT) {
|
|
562
|
-
env.DECO_REQUEST_CONTEXT.ensureAuthenticated();
|
|
563
|
-
const redirectTo = new URL("/", url);
|
|
564
|
-
const next = url.searchParams.get("next");
|
|
565
|
-
return Response.redirect(next ?? redirectTo, 302);
|
|
566
|
-
}
|
|
567
|
-
if (url.pathname === AUTH_LOGOUT_ENDPOINT) {
|
|
568
|
-
return handleLogout(req);
|
|
569
|
-
}
|
|
570
|
-
if (url.pathname === "/mcp") {
|
|
571
|
-
return server.fetch(req, env, ctx);
|
|
572
|
-
}
|
|
573
|
-
if (url.pathname.startsWith("/mcp/call-tool")) {
|
|
574
|
-
const toolCallId = url.pathname.split("/").pop();
|
|
575
|
-
if (!toolCallId) {
|
|
576
|
-
return new Response("Not found", { status: 404 });
|
|
577
|
-
}
|
|
578
|
-
const toolCallInput = await req.json();
|
|
579
|
-
const result = await server.callTool({
|
|
580
|
-
toolCallId,
|
|
581
|
-
toolCallInput
|
|
582
|
-
});
|
|
583
|
-
if (result instanceof Response) {
|
|
584
|
-
return result;
|
|
585
|
-
}
|
|
586
|
-
return new Response(JSON.stringify(result), {
|
|
587
|
-
headers: {
|
|
588
|
-
"Content-Type": "application/json"
|
|
589
|
-
}
|
|
590
|
-
});
|
|
591
|
-
}
|
|
592
|
-
if (url.pathname.startsWith(DeconfigResource.WatchPathNameBase)) {
|
|
593
|
-
return DeconfigResource.watchAPI(req, env);
|
|
594
|
-
}
|
|
595
|
-
return userFns.fetch?.(req, env, ctx) || new Response("Not found", { status: 404 });
|
|
596
|
-
};
|
|
597
|
-
return {
|
|
598
|
-
Workflow: Workflow(server, userFns.workflows),
|
|
599
|
-
fetch: async (req, env, ctx) => {
|
|
600
|
-
const referer = req.headers.get("referer");
|
|
601
|
-
const isFetchRequest = req.headers.has(DECO_MCP_CLIENT_HEADER);
|
|
602
|
-
try {
|
|
603
|
-
const bindings = withBindings({
|
|
604
|
-
env,
|
|
605
|
-
server,
|
|
606
|
-
branch: req.headers.get("x-deco-branch") ?? new URL(req.url).searchParams.get("__b"),
|
|
607
|
-
tokenOrContext: await getReqToken(req, env),
|
|
608
|
-
origin: referer ?? req.headers.get("origin") ?? new URL(req.url).origin,
|
|
609
|
-
url: req.url
|
|
610
|
-
});
|
|
611
|
-
return await State.run(
|
|
612
|
-
{ req, env: bindings, ctx },
|
|
613
|
-
async () => await fetcher(req, bindings, ctx)
|
|
614
|
-
);
|
|
615
|
-
} catch (error) {
|
|
616
|
-
if (error instanceof UnauthorizedError) {
|
|
617
|
-
if (!isFetchRequest) {
|
|
618
|
-
const url = new URL(req.url);
|
|
619
|
-
error.redirectTo.searchParams.set(
|
|
620
|
-
"state",
|
|
621
|
-
StateParser.stringify({
|
|
622
|
-
next: url.searchParams.get("next") ?? referer ?? req.url
|
|
623
|
-
})
|
|
624
|
-
);
|
|
625
|
-
return Response.redirect(error.redirectTo, 302);
|
|
626
|
-
}
|
|
627
|
-
return new Response(null, { status: 401 });
|
|
628
|
-
}
|
|
629
|
-
throw error;
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
};
|
|
633
|
-
};
|
|
634
|
-
|
|
635
|
-
export { UnauthorizedError, WorkersMCPBindings, proxyConnectionForId, withBindings, withRuntime };
|
|
636
|
-
//# sourceMappingURL=index.js.map
|
|
637
|
-
//# sourceMappingURL=index.js.map
|