skedyul 1.2.21 → 1.2.23
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/dist/cli/index.js +464 -631
- package/dist/config/types/env.d.ts +8 -2
- package/dist/config/types/form.d.ts +10 -6
- package/dist/config/types/index.d.ts +0 -1
- package/dist/config/types/page.d.ts +2 -2
- package/dist/config/types/webhook.d.ts +2 -1
- package/dist/dedicated/server.js +464 -679
- package/dist/esm/index.mjs +464 -631
- package/dist/index.d.ts +1 -2
- package/dist/index.js +464 -631
- package/dist/server/dedicated.d.ts +1 -1
- package/dist/server/handlers/index.d.ts +12 -0
- package/dist/server/handlers/install-handler.d.ts +9 -0
- package/dist/server/handlers/oauth-callback-handler.d.ts +9 -0
- package/dist/server/handlers/provision-handler.d.ts +9 -0
- package/dist/server/handlers/types.d.ts +101 -0
- package/dist/server/handlers/uninstall-handler.d.ts +9 -0
- package/dist/server/handlers/webhook-handler.d.ts +28 -0
- package/dist/server/serverless.d.ts +1 -1
- package/dist/server/tool-handler.d.ts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +464 -679
- package/dist/serverless/server.mjs +464 -657
- package/dist/types/handlers.d.ts +6 -24
- package/dist/types/index.d.ts +3 -3
- package/dist/types/server.d.ts +1 -1
- package/dist/types/shared.d.ts +5 -0
- package/dist/types/tool.d.ts +5 -7
- package/dist/types/webhook.d.ts +14 -6
- package/package.json +1 -1
- package/dist/config/types/compute.d.ts +0 -9
package/dist/dedicated/server.js
CHANGED
|
@@ -30,32 +30,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/server.ts
|
|
31
31
|
var server_exports = {};
|
|
32
32
|
__export(server_exports, {
|
|
33
|
-
buildRequestFromRaw: () => buildRequestFromRaw,
|
|
34
|
-
buildRequestScopedConfig: () => buildRequestScopedConfig,
|
|
35
|
-
buildToolMetadata: () => buildToolMetadata,
|
|
36
|
-
createCallToolHandler: () => createCallToolHandler,
|
|
37
|
-
createDedicatedServerInstance: () => createDedicatedServerInstance,
|
|
38
|
-
createRequestState: () => createRequestState,
|
|
39
|
-
createResponse: () => createResponse,
|
|
40
|
-
createServerlessInstance: () => createServerlessInstance,
|
|
41
33
|
createSkedyulServer: () => createSkedyulServer,
|
|
42
|
-
getDefaultHeaders: () => getDefaultHeaders,
|
|
43
34
|
getJsonSchemaFromToolSchema: () => getJsonSchemaFromToolSchema,
|
|
44
|
-
getListeningPort: () => getListeningPort,
|
|
45
35
|
getZodSchema: () => getZodSchema,
|
|
46
|
-
handleCoreMethod: () => handleCoreMethod,
|
|
47
36
|
isToolSchemaWithJson: () => isToolSchemaWithJson,
|
|
48
|
-
mergeRuntimeEnv: () => mergeRuntimeEnv,
|
|
49
|
-
normalizeBilling: () => normalizeBilling,
|
|
50
|
-
padEnd: () => padEnd,
|
|
51
|
-
parseHandlerEnvelope: () => parseHandlerEnvelope,
|
|
52
|
-
parseJSONBody: () => parseJSONBody,
|
|
53
|
-
parseJsonRecord: () => parseJsonRecord,
|
|
54
|
-
parseNumberEnv: () => parseNumberEnv,
|
|
55
|
-
printStartupLog: () => printStartupLog,
|
|
56
|
-
readRawRequestBody: () => readRawRequestBody,
|
|
57
|
-
sendHTML: () => sendHTML,
|
|
58
|
-
sendJSON: () => sendJSON,
|
|
59
37
|
server: () => server,
|
|
60
38
|
toJsonSchema: () => toJsonSchema
|
|
61
39
|
});
|
|
@@ -203,10 +181,6 @@ function sendJSON(res, statusCode, data) {
|
|
|
203
181
|
res.writeHead(statusCode, { "Content-Type": "application/json" });
|
|
204
182
|
res.end(JSON.stringify(data));
|
|
205
183
|
}
|
|
206
|
-
function sendHTML(res, statusCode, html) {
|
|
207
|
-
res.writeHead(statusCode, { "Content-Type": "text/html; charset=utf-8" });
|
|
208
|
-
res.end(html);
|
|
209
|
-
}
|
|
210
184
|
function getDefaultHeaders(options) {
|
|
211
185
|
return {
|
|
212
186
|
"Content-Type": "application/json",
|
|
@@ -392,8 +366,8 @@ function createRequestState(maxRequests, ttlExtendSeconds, runtimeLabel, toolNam
|
|
|
392
366
|
};
|
|
393
367
|
}
|
|
394
368
|
function createCallToolHandler(registry, state, onMaxRequests) {
|
|
395
|
-
return async function callTool(
|
|
396
|
-
const toolName = String(
|
|
369
|
+
return async function callTool(toolNameInput, toolArgsInput) {
|
|
370
|
+
const toolName = String(toolNameInput);
|
|
397
371
|
const tool = registry[toolName];
|
|
398
372
|
if (!tool) {
|
|
399
373
|
throw new Error(`Tool "${toolName}" not found in registry`);
|
|
@@ -402,7 +376,7 @@ function createCallToolHandler(registry, state, onMaxRequests) {
|
|
|
402
376
|
throw new Error(`Tool "${toolName}" handler is not a function`);
|
|
403
377
|
}
|
|
404
378
|
const fn = tool.handler;
|
|
405
|
-
const args =
|
|
379
|
+
const args = toolArgsInput ?? {};
|
|
406
380
|
const estimateMode = args.estimate === true;
|
|
407
381
|
if (!estimateMode) {
|
|
408
382
|
state.incrementRequestCount();
|
|
@@ -657,51 +631,6 @@ async function handleCoreMethod(method, params) {
|
|
|
657
631
|
};
|
|
658
632
|
}
|
|
659
633
|
|
|
660
|
-
// src/server/handler-helpers.ts
|
|
661
|
-
function parseHandlerEnvelope(parsedBody) {
|
|
662
|
-
if (typeof parsedBody !== "object" || parsedBody === null || Array.isArray(parsedBody) || !("env" in parsedBody) || !("request" in parsedBody)) {
|
|
663
|
-
return null;
|
|
664
|
-
}
|
|
665
|
-
const envelope = parsedBody;
|
|
666
|
-
if (typeof envelope.env !== "object" || envelope.env === null || Array.isArray(envelope.env)) {
|
|
667
|
-
return null;
|
|
668
|
-
}
|
|
669
|
-
if (typeof envelope.request !== "object" || envelope.request === null || Array.isArray(envelope.request)) {
|
|
670
|
-
return null;
|
|
671
|
-
}
|
|
672
|
-
return {
|
|
673
|
-
env: envelope.env,
|
|
674
|
-
request: envelope.request,
|
|
675
|
-
context: envelope.context
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
|
-
function buildRequestFromRaw(raw) {
|
|
679
|
-
let parsedBody = raw.body;
|
|
680
|
-
const contentType = raw.headers["content-type"] ?? "";
|
|
681
|
-
if (contentType.includes("application/json")) {
|
|
682
|
-
try {
|
|
683
|
-
parsedBody = raw.body ? JSON.parse(raw.body) : {};
|
|
684
|
-
} catch {
|
|
685
|
-
parsedBody = raw.body;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
return {
|
|
689
|
-
method: raw.method,
|
|
690
|
-
url: raw.url,
|
|
691
|
-
path: raw.path,
|
|
692
|
-
headers: raw.headers,
|
|
693
|
-
query: raw.query,
|
|
694
|
-
body: parsedBody,
|
|
695
|
-
rawBody: raw.body ? Buffer.from(raw.body, "utf-8") : void 0
|
|
696
|
-
};
|
|
697
|
-
}
|
|
698
|
-
function buildRequestScopedConfig(env) {
|
|
699
|
-
return {
|
|
700
|
-
baseUrl: env.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
|
|
701
|
-
apiToken: env.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
|
|
702
|
-
};
|
|
703
|
-
}
|
|
704
|
-
|
|
705
634
|
// src/server/startup-logger.ts
|
|
706
635
|
function padEnd(str, length) {
|
|
707
636
|
if (str.length >= length) {
|
|
@@ -799,6 +728,405 @@ function isProvisionConfig(value) {
|
|
|
799
728
|
return value !== void 0 && value !== null && !(value instanceof Promise);
|
|
800
729
|
}
|
|
801
730
|
|
|
731
|
+
// src/server/handlers/install-handler.ts
|
|
732
|
+
async function handleInstall(body, hooks) {
|
|
733
|
+
if (!hooks?.install) {
|
|
734
|
+
return {
|
|
735
|
+
status: 404,
|
|
736
|
+
body: { error: "Install handler not configured" }
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
if (!body.context?.appInstallationId || !body.context?.workplace) {
|
|
740
|
+
return {
|
|
741
|
+
status: 400,
|
|
742
|
+
body: {
|
|
743
|
+
error: {
|
|
744
|
+
code: -32602,
|
|
745
|
+
message: "Missing context (appInstallationId and workplace required)"
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
const installContext = {
|
|
751
|
+
env: body.env ?? {},
|
|
752
|
+
workplace: body.context.workplace,
|
|
753
|
+
appInstallationId: body.context.appInstallationId,
|
|
754
|
+
app: body.context.app,
|
|
755
|
+
invocation: body.invocation,
|
|
756
|
+
log: createContextLogger()
|
|
757
|
+
};
|
|
758
|
+
const requestConfig = {
|
|
759
|
+
baseUrl: body.env?.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
|
|
760
|
+
apiToken: body.env?.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
|
|
761
|
+
};
|
|
762
|
+
try {
|
|
763
|
+
const installHook = hooks.install;
|
|
764
|
+
const installHandler = typeof installHook === "function" ? installHook : installHook.handler;
|
|
765
|
+
const result = await runWithLogContext({ invocation: body.invocation }, async () => {
|
|
766
|
+
return await runWithConfig(requestConfig, async () => {
|
|
767
|
+
return await installHandler(installContext);
|
|
768
|
+
});
|
|
769
|
+
});
|
|
770
|
+
return {
|
|
771
|
+
status: 200,
|
|
772
|
+
body: { env: result.env ?? {}, redirect: result.redirect }
|
|
773
|
+
};
|
|
774
|
+
} catch (err) {
|
|
775
|
+
if (err instanceof InstallError) {
|
|
776
|
+
return {
|
|
777
|
+
status: 400,
|
|
778
|
+
body: {
|
|
779
|
+
error: {
|
|
780
|
+
code: err.code,
|
|
781
|
+
message: err.message,
|
|
782
|
+
field: err.field
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
return {
|
|
788
|
+
status: 500,
|
|
789
|
+
body: {
|
|
790
|
+
error: {
|
|
791
|
+
code: -32603,
|
|
792
|
+
message: err instanceof Error ? err.message : String(err ?? "")
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
// src/server/handlers/uninstall-handler.ts
|
|
800
|
+
async function handleUninstall(body, hooks) {
|
|
801
|
+
if (!hooks?.uninstall) {
|
|
802
|
+
return {
|
|
803
|
+
status: 404,
|
|
804
|
+
body: { error: "Uninstall handler not configured" }
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
if (!body.context?.appInstallationId || !body.context?.workplace || !body.context?.app) {
|
|
808
|
+
return {
|
|
809
|
+
status: 400,
|
|
810
|
+
body: {
|
|
811
|
+
error: {
|
|
812
|
+
code: -32602,
|
|
813
|
+
message: "Missing context (appInstallationId, workplace and app required)"
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
const uninstallContext = {
|
|
819
|
+
env: body.env ?? {},
|
|
820
|
+
workplace: body.context.workplace,
|
|
821
|
+
appInstallationId: body.context.appInstallationId,
|
|
822
|
+
app: body.context.app,
|
|
823
|
+
invocation: body.invocation,
|
|
824
|
+
log: createContextLogger()
|
|
825
|
+
};
|
|
826
|
+
const requestConfig = {
|
|
827
|
+
baseUrl: body.env?.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
|
|
828
|
+
apiToken: body.env?.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
|
|
829
|
+
};
|
|
830
|
+
try {
|
|
831
|
+
const uninstallHook = hooks.uninstall;
|
|
832
|
+
const uninstallHandlerFn = typeof uninstallHook === "function" ? uninstallHook : uninstallHook.handler;
|
|
833
|
+
const result = await runWithLogContext({ invocation: body.invocation }, async () => {
|
|
834
|
+
return await runWithConfig(requestConfig, async () => {
|
|
835
|
+
return await uninstallHandlerFn(uninstallContext);
|
|
836
|
+
});
|
|
837
|
+
});
|
|
838
|
+
return {
|
|
839
|
+
status: 200,
|
|
840
|
+
body: { cleanedWebhookIds: result.cleanedWebhookIds ?? [] }
|
|
841
|
+
};
|
|
842
|
+
} catch (err) {
|
|
843
|
+
return {
|
|
844
|
+
status: 500,
|
|
845
|
+
body: {
|
|
846
|
+
error: {
|
|
847
|
+
code: -32603,
|
|
848
|
+
message: err instanceof Error ? err.message : String(err ?? "")
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// src/server/handlers/provision-handler.ts
|
|
856
|
+
async function handleProvision(body, hooks) {
|
|
857
|
+
if (!hooks?.provision) {
|
|
858
|
+
return {
|
|
859
|
+
status: 404,
|
|
860
|
+
body: { error: "Provision handler not configured" }
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
if (!body.context?.app) {
|
|
864
|
+
return {
|
|
865
|
+
status: 400,
|
|
866
|
+
body: {
|
|
867
|
+
error: {
|
|
868
|
+
code: -32602,
|
|
869
|
+
message: "Missing context (app required)"
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
const mergedEnv = {};
|
|
875
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
876
|
+
if (value !== void 0) {
|
|
877
|
+
mergedEnv[key] = value;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
Object.assign(mergedEnv, body.env ?? {});
|
|
881
|
+
const provisionContext = {
|
|
882
|
+
env: mergedEnv,
|
|
883
|
+
app: body.context.app,
|
|
884
|
+
invocation: body.invocation,
|
|
885
|
+
log: createContextLogger()
|
|
886
|
+
};
|
|
887
|
+
const requestConfig = {
|
|
888
|
+
baseUrl: mergedEnv.SKEDYUL_API_URL ?? "",
|
|
889
|
+
apiToken: mergedEnv.SKEDYUL_API_TOKEN ?? ""
|
|
890
|
+
};
|
|
891
|
+
try {
|
|
892
|
+
const provisionHook = hooks.provision;
|
|
893
|
+
const provisionHandler = typeof provisionHook === "function" ? provisionHook : provisionHook.handler;
|
|
894
|
+
const result = await runWithLogContext({ invocation: body.invocation }, async () => {
|
|
895
|
+
return await runWithConfig(requestConfig, async () => {
|
|
896
|
+
return await provisionHandler(provisionContext);
|
|
897
|
+
});
|
|
898
|
+
});
|
|
899
|
+
return {
|
|
900
|
+
status: 200,
|
|
901
|
+
body: result
|
|
902
|
+
};
|
|
903
|
+
} catch (err) {
|
|
904
|
+
return {
|
|
905
|
+
status: 500,
|
|
906
|
+
body: {
|
|
907
|
+
error: {
|
|
908
|
+
code: -32603,
|
|
909
|
+
message: err instanceof Error ? err.message : String(err ?? "")
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
// src/server/handler-helpers.ts
|
|
917
|
+
function parseHandlerEnvelope(parsedBody) {
|
|
918
|
+
if (typeof parsedBody !== "object" || parsedBody === null || Array.isArray(parsedBody) || !("env" in parsedBody) || !("request" in parsedBody)) {
|
|
919
|
+
return null;
|
|
920
|
+
}
|
|
921
|
+
const envelope = parsedBody;
|
|
922
|
+
if (typeof envelope.env !== "object" || envelope.env === null || Array.isArray(envelope.env)) {
|
|
923
|
+
return null;
|
|
924
|
+
}
|
|
925
|
+
if (typeof envelope.request !== "object" || envelope.request === null || Array.isArray(envelope.request)) {
|
|
926
|
+
return null;
|
|
927
|
+
}
|
|
928
|
+
return {
|
|
929
|
+
env: envelope.env,
|
|
930
|
+
request: envelope.request,
|
|
931
|
+
context: envelope.context
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
function buildRequestFromRaw(raw) {
|
|
935
|
+
let parsedBody = raw.body;
|
|
936
|
+
const contentType = raw.headers["content-type"] ?? "";
|
|
937
|
+
if (contentType.includes("application/json")) {
|
|
938
|
+
try {
|
|
939
|
+
parsedBody = raw.body ? JSON.parse(raw.body) : {};
|
|
940
|
+
} catch {
|
|
941
|
+
parsedBody = raw.body;
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
return {
|
|
945
|
+
method: raw.method,
|
|
946
|
+
url: raw.url,
|
|
947
|
+
path: raw.path,
|
|
948
|
+
headers: raw.headers,
|
|
949
|
+
query: raw.query,
|
|
950
|
+
body: parsedBody,
|
|
951
|
+
rawBody: raw.body ? Buffer.from(raw.body, "utf-8") : void 0
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
function buildRequestScopedConfig(env) {
|
|
955
|
+
return {
|
|
956
|
+
baseUrl: env.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
|
|
957
|
+
apiToken: env.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
// src/server/handlers/oauth-callback-handler.ts
|
|
962
|
+
async function handleOAuthCallback(parsedBody, hooks) {
|
|
963
|
+
if (!hooks?.oauth_callback) {
|
|
964
|
+
return {
|
|
965
|
+
status: 404,
|
|
966
|
+
body: { error: "OAuth callback handler not configured" }
|
|
967
|
+
};
|
|
968
|
+
}
|
|
969
|
+
const envelope = parseHandlerEnvelope(parsedBody);
|
|
970
|
+
if (!envelope) {
|
|
971
|
+
console.error("[OAuth Callback] Failed to parse envelope. Body:", JSON.stringify(parsedBody, null, 2));
|
|
972
|
+
return {
|
|
973
|
+
status: 400,
|
|
974
|
+
body: {
|
|
975
|
+
error: {
|
|
976
|
+
code: -32602,
|
|
977
|
+
message: "Missing envelope format: expected { env, request }"
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
const invocation = parsedBody.invocation;
|
|
983
|
+
const oauthRequest = buildRequestFromRaw(envelope.request);
|
|
984
|
+
const requestConfig = buildRequestScopedConfig(envelope.env);
|
|
985
|
+
const oauthCallbackContext = {
|
|
986
|
+
request: oauthRequest,
|
|
987
|
+
invocation,
|
|
988
|
+
log: createContextLogger()
|
|
989
|
+
};
|
|
990
|
+
try {
|
|
991
|
+
const oauthCallbackHook = hooks.oauth_callback;
|
|
992
|
+
const oauthCallbackHandler = typeof oauthCallbackHook === "function" ? oauthCallbackHook : oauthCallbackHook.handler;
|
|
993
|
+
const result = await runWithLogContext({ invocation }, async () => {
|
|
994
|
+
return await runWithConfig(requestConfig, async () => {
|
|
995
|
+
return await oauthCallbackHandler(oauthCallbackContext);
|
|
996
|
+
});
|
|
997
|
+
});
|
|
998
|
+
return {
|
|
999
|
+
status: 200,
|
|
1000
|
+
body: {
|
|
1001
|
+
appInstallationId: result.appInstallationId,
|
|
1002
|
+
env: result.env ?? {}
|
|
1003
|
+
}
|
|
1004
|
+
};
|
|
1005
|
+
} catch (err) {
|
|
1006
|
+
const errorMessage = err instanceof Error ? err.message : String(err ?? "Unknown error");
|
|
1007
|
+
return {
|
|
1008
|
+
status: 500,
|
|
1009
|
+
body: {
|
|
1010
|
+
error: {
|
|
1011
|
+
code: -32603,
|
|
1012
|
+
message: errorMessage
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
// src/server/handlers/webhook-handler.ts
|
|
1020
|
+
function parseWebhookRequest(parsedBody, method, url, path, headers, query, rawBody, appIdHeader, appVersionIdHeader) {
|
|
1021
|
+
const isEnvelope = typeof parsedBody === "object" && parsedBody !== null && "env" in parsedBody && "request" in parsedBody && "context" in parsedBody;
|
|
1022
|
+
if (isEnvelope) {
|
|
1023
|
+
const envelope = parsedBody;
|
|
1024
|
+
const requestEnv = envelope.env ?? {};
|
|
1025
|
+
const invocation = envelope.invocation;
|
|
1026
|
+
let originalParsedBody = envelope.request.body;
|
|
1027
|
+
const originalContentType = envelope.request.headers["content-type"] ?? "";
|
|
1028
|
+
if (originalContentType.includes("application/json")) {
|
|
1029
|
+
try {
|
|
1030
|
+
originalParsedBody = envelope.request.body ? JSON.parse(envelope.request.body) : {};
|
|
1031
|
+
} catch {
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
const webhookRequest2 = {
|
|
1035
|
+
method: envelope.request.method,
|
|
1036
|
+
url: envelope.request.url,
|
|
1037
|
+
path: envelope.request.path,
|
|
1038
|
+
headers: envelope.request.headers,
|
|
1039
|
+
query: envelope.request.query,
|
|
1040
|
+
body: originalParsedBody,
|
|
1041
|
+
rawBody: envelope.request.body ? Buffer.from(envelope.request.body, "utf-8") : void 0
|
|
1042
|
+
};
|
|
1043
|
+
const envVars = { ...process.env, ...requestEnv };
|
|
1044
|
+
const app = envelope.context.app;
|
|
1045
|
+
let webhookContext2;
|
|
1046
|
+
if (envelope.context.appInstallationId && envelope.context.workplace) {
|
|
1047
|
+
webhookContext2 = {
|
|
1048
|
+
env: envVars,
|
|
1049
|
+
app,
|
|
1050
|
+
appInstallationId: envelope.context.appInstallationId,
|
|
1051
|
+
workplace: envelope.context.workplace,
|
|
1052
|
+
registration: envelope.context.registration ?? {},
|
|
1053
|
+
invocation,
|
|
1054
|
+
log: createContextLogger()
|
|
1055
|
+
};
|
|
1056
|
+
} else {
|
|
1057
|
+
webhookContext2 = {
|
|
1058
|
+
env: envVars,
|
|
1059
|
+
app,
|
|
1060
|
+
invocation,
|
|
1061
|
+
log: createContextLogger()
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
return { webhookRequest: webhookRequest2, webhookContext: webhookContext2, requestEnv, invocation };
|
|
1065
|
+
}
|
|
1066
|
+
if (!appIdHeader || !appVersionIdHeader) {
|
|
1067
|
+
return {
|
|
1068
|
+
error: "Missing app info in webhook request (x-skedyul-app-id and x-skedyul-app-version-id headers required)"
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
const webhookRequest = {
|
|
1072
|
+
method,
|
|
1073
|
+
url,
|
|
1074
|
+
path,
|
|
1075
|
+
headers,
|
|
1076
|
+
query,
|
|
1077
|
+
body: parsedBody,
|
|
1078
|
+
rawBody: rawBody ? Buffer.from(rawBody, "utf-8") : void 0
|
|
1079
|
+
};
|
|
1080
|
+
const webhookContext = {
|
|
1081
|
+
env: process.env,
|
|
1082
|
+
app: { id: appIdHeader, versionId: appVersionIdHeader },
|
|
1083
|
+
log: createContextLogger()
|
|
1084
|
+
};
|
|
1085
|
+
return { webhookRequest, webhookContext, requestEnv: {} };
|
|
1086
|
+
}
|
|
1087
|
+
async function executeWebhookHandler(handle, webhookRegistry, data) {
|
|
1088
|
+
const webhookDef = webhookRegistry[handle];
|
|
1089
|
+
if (!webhookDef) {
|
|
1090
|
+
return {
|
|
1091
|
+
status: 404,
|
|
1092
|
+
body: { error: `Webhook handler '${handle}' not found` }
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
const originalEnv = { ...process.env };
|
|
1096
|
+
Object.assign(process.env, data.requestEnv);
|
|
1097
|
+
const requestConfig = {
|
|
1098
|
+
baseUrl: data.requestEnv.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
|
|
1099
|
+
apiToken: data.requestEnv.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
|
|
1100
|
+
};
|
|
1101
|
+
let webhookResponse;
|
|
1102
|
+
try {
|
|
1103
|
+
webhookResponse = await runWithLogContext({ invocation: data.invocation }, async () => {
|
|
1104
|
+
return await runWithConfig(requestConfig, async () => {
|
|
1105
|
+
return await webhookDef.handler(data.webhookRequest, data.webhookContext);
|
|
1106
|
+
});
|
|
1107
|
+
});
|
|
1108
|
+
} catch (err) {
|
|
1109
|
+
console.error(`Webhook handler '${handle}' error:`, err);
|
|
1110
|
+
return {
|
|
1111
|
+
status: 500,
|
|
1112
|
+
body: { error: "Webhook handler error" }
|
|
1113
|
+
};
|
|
1114
|
+
} finally {
|
|
1115
|
+
process.env = originalEnv;
|
|
1116
|
+
}
|
|
1117
|
+
return {
|
|
1118
|
+
status: webhookResponse.status ?? 200,
|
|
1119
|
+
body: webhookResponse.body,
|
|
1120
|
+
headers: webhookResponse.headers
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
function isMethodAllowed(webhookRegistry, handle, method) {
|
|
1124
|
+
const webhookDef = webhookRegistry[handle];
|
|
1125
|
+
if (!webhookDef) return false;
|
|
1126
|
+
const allowedMethods = webhookDef.methods ?? ["POST"];
|
|
1127
|
+
return allowedMethods.includes(method);
|
|
1128
|
+
}
|
|
1129
|
+
|
|
802
1130
|
// src/server/dedicated.ts
|
|
803
1131
|
function createDedicatedServerInstance(config, tools, callTool, state, mcpServer) {
|
|
804
1132
|
const port = getListeningPort(config);
|
|
@@ -825,13 +1153,11 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
|
|
|
825
1153
|
}
|
|
826
1154
|
if (pathname.startsWith("/webhooks/") && webhookRegistry) {
|
|
827
1155
|
const handle = pathname.slice("/webhooks/".length);
|
|
828
|
-
|
|
829
|
-
if (!webhookDef) {
|
|
1156
|
+
if (!webhookRegistry[handle]) {
|
|
830
1157
|
sendJSON(res, 404, { error: `Webhook handler '${handle}' not found` });
|
|
831
1158
|
return;
|
|
832
1159
|
}
|
|
833
|
-
|
|
834
|
-
if (!allowedMethods.includes(req.method)) {
|
|
1160
|
+
if (!isMethodAllowed(webhookRegistry, handle, req.method ?? "POST")) {
|
|
835
1161
|
sendJSON(res, 405, { error: `Method ${req.method} not allowed` });
|
|
836
1162
|
return;
|
|
837
1163
|
}
|
|
@@ -853,87 +1179,34 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
|
|
|
853
1179
|
} else {
|
|
854
1180
|
parsedBody = rawBody;
|
|
855
1181
|
}
|
|
856
|
-
const
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
webhookContext = {
|
|
870
|
-
env: envVars,
|
|
871
|
-
app,
|
|
872
|
-
appInstallationId: context.appInstallationId,
|
|
873
|
-
workplace: context.workplace,
|
|
874
|
-
registration: context.registration ?? {},
|
|
875
|
-
invocation,
|
|
876
|
-
log: createContextLogger()
|
|
877
|
-
};
|
|
878
|
-
} else {
|
|
879
|
-
webhookContext = {
|
|
880
|
-
env: envVars,
|
|
881
|
-
app,
|
|
882
|
-
invocation,
|
|
883
|
-
log: createContextLogger()
|
|
884
|
-
};
|
|
885
|
-
}
|
|
886
|
-
} else {
|
|
887
|
-
const appId = req.headers["x-skedyul-app-id"];
|
|
888
|
-
const appVersionId = req.headers["x-skedyul-app-version-id"];
|
|
889
|
-
if (!appId || !appVersionId) {
|
|
890
|
-
throw new Error("Missing app info in webhook request (x-skedyul-app-id and x-skedyul-app-version-id headers required)");
|
|
891
|
-
}
|
|
892
|
-
webhookRequest = {
|
|
893
|
-
method: req.method ?? "POST",
|
|
894
|
-
url: url.toString(),
|
|
895
|
-
path: pathname,
|
|
896
|
-
headers: req.headers,
|
|
897
|
-
query: Object.fromEntries(url.searchParams.entries()),
|
|
898
|
-
body: parsedBody,
|
|
899
|
-
rawBody: rawBody ? Buffer.from(rawBody, "utf-8") : void 0
|
|
900
|
-
};
|
|
901
|
-
webhookContext = {
|
|
902
|
-
env: process.env,
|
|
903
|
-
app: { id: appId, versionId: appVersionId },
|
|
904
|
-
log: createContextLogger()
|
|
905
|
-
};
|
|
906
|
-
}
|
|
907
|
-
const originalEnv = { ...process.env };
|
|
908
|
-
Object.assign(process.env, requestEnv);
|
|
909
|
-
const requestConfig = buildRequestScopedConfig(requestEnv);
|
|
910
|
-
let webhookResponse;
|
|
911
|
-
try {
|
|
912
|
-
webhookResponse = await runWithLogContext({ invocation }, async () => {
|
|
913
|
-
return await runWithConfig(requestConfig, async () => {
|
|
914
|
-
return await webhookDef.handler(webhookRequest, webhookContext);
|
|
915
|
-
});
|
|
916
|
-
});
|
|
917
|
-
} catch (err) {
|
|
918
|
-
console.error(`Webhook handler '${handle}' error:`, err);
|
|
919
|
-
sendJSON(res, 500, { error: "Webhook handler error" });
|
|
1182
|
+
const parseResult = parseWebhookRequest(
|
|
1183
|
+
parsedBody,
|
|
1184
|
+
req.method ?? "POST",
|
|
1185
|
+
url.toString(),
|
|
1186
|
+
pathname,
|
|
1187
|
+
req.headers,
|
|
1188
|
+
Object.fromEntries(url.searchParams.entries()),
|
|
1189
|
+
rawBody,
|
|
1190
|
+
req.headers["x-skedyul-app-id"],
|
|
1191
|
+
req.headers["x-skedyul-app-version-id"]
|
|
1192
|
+
);
|
|
1193
|
+
if ("error" in parseResult) {
|
|
1194
|
+
sendJSON(res, 400, { error: parseResult.error });
|
|
920
1195
|
return;
|
|
921
|
-
} finally {
|
|
922
|
-
process.env = originalEnv;
|
|
923
1196
|
}
|
|
924
|
-
const
|
|
1197
|
+
const result = await executeWebhookHandler(handle, webhookRegistry, parseResult);
|
|
925
1198
|
const responseHeaders = {
|
|
926
|
-
...
|
|
1199
|
+
...result.headers
|
|
927
1200
|
};
|
|
928
1201
|
if (!responseHeaders["Content-Type"] && !responseHeaders["content-type"]) {
|
|
929
1202
|
responseHeaders["Content-Type"] = "application/json";
|
|
930
1203
|
}
|
|
931
|
-
res.writeHead(status, responseHeaders);
|
|
932
|
-
if (
|
|
933
|
-
if (typeof
|
|
934
|
-
res.end(
|
|
1204
|
+
res.writeHead(result.status, responseHeaders);
|
|
1205
|
+
if (result.body !== void 0) {
|
|
1206
|
+
if (typeof result.body === "string") {
|
|
1207
|
+
res.end(result.body);
|
|
935
1208
|
} else {
|
|
936
|
-
res.end(JSON.stringify(
|
|
1209
|
+
res.end(JSON.stringify(result.body));
|
|
937
1210
|
}
|
|
938
1211
|
} else {
|
|
939
1212
|
res.end();
|
|
@@ -972,10 +1245,6 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
|
|
|
972
1245
|
return;
|
|
973
1246
|
}
|
|
974
1247
|
if (pathname === "/oauth_callback" && req.method === "POST") {
|
|
975
|
-
if (!config.hooks?.oauth_callback) {
|
|
976
|
-
sendJSON(res, 404, { error: "OAuth callback handler not configured" });
|
|
977
|
-
return;
|
|
978
|
-
}
|
|
979
1248
|
let parsedBody;
|
|
980
1249
|
try {
|
|
981
1250
|
parsedBody = await parseJSONBody(req);
|
|
@@ -986,50 +1255,11 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
|
|
|
986
1255
|
});
|
|
987
1256
|
return;
|
|
988
1257
|
}
|
|
989
|
-
const
|
|
990
|
-
|
|
991
|
-
console.error("[OAuth Callback] Failed to parse envelope. Body:", JSON.stringify(parsedBody, null, 2));
|
|
992
|
-
sendJSON(res, 400, {
|
|
993
|
-
error: { code: -32602, message: "Missing envelope format: expected { env, request }" }
|
|
994
|
-
});
|
|
995
|
-
return;
|
|
996
|
-
}
|
|
997
|
-
const invocation = parsedBody.invocation;
|
|
998
|
-
const oauthRequest = buildRequestFromRaw(envelope.request);
|
|
999
|
-
const oauthCallbackRequestConfig = buildRequestScopedConfig(envelope.env);
|
|
1000
|
-
const oauthCallbackContext = {
|
|
1001
|
-
request: oauthRequest,
|
|
1002
|
-
invocation,
|
|
1003
|
-
log: createContextLogger()
|
|
1004
|
-
};
|
|
1005
|
-
try {
|
|
1006
|
-
const oauthCallbackHook = config.hooks.oauth_callback;
|
|
1007
|
-
const oauthCallbackHandler = typeof oauthCallbackHook === "function" ? oauthCallbackHook : oauthCallbackHook.handler;
|
|
1008
|
-
const result = await runWithLogContext({ invocation }, async () => {
|
|
1009
|
-
return await runWithConfig(oauthCallbackRequestConfig, async () => {
|
|
1010
|
-
return await oauthCallbackHandler(oauthCallbackContext);
|
|
1011
|
-
});
|
|
1012
|
-
});
|
|
1013
|
-
sendJSON(res, 200, {
|
|
1014
|
-
appInstallationId: result.appInstallationId,
|
|
1015
|
-
env: result.env ?? {}
|
|
1016
|
-
});
|
|
1017
|
-
} catch (err) {
|
|
1018
|
-
const errorMessage = err instanceof Error ? err.message : String(err ?? "Unknown error");
|
|
1019
|
-
sendJSON(res, 500, {
|
|
1020
|
-
error: {
|
|
1021
|
-
code: -32603,
|
|
1022
|
-
message: errorMessage
|
|
1023
|
-
}
|
|
1024
|
-
});
|
|
1025
|
-
}
|
|
1258
|
+
const result = await handleOAuthCallback(parsedBody, config.hooks);
|
|
1259
|
+
sendJSON(res, result.status, result.body);
|
|
1026
1260
|
return;
|
|
1027
1261
|
}
|
|
1028
1262
|
if (pathname === "/install" && req.method === "POST") {
|
|
1029
|
-
if (!config.hooks?.install) {
|
|
1030
|
-
sendJSON(res, 404, { error: "Install handler not configured" });
|
|
1031
|
-
return;
|
|
1032
|
-
}
|
|
1033
1263
|
let installBody;
|
|
1034
1264
|
try {
|
|
1035
1265
|
installBody = await parseJSONBody(req);
|
|
@@ -1039,61 +1269,11 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
|
|
|
1039
1269
|
});
|
|
1040
1270
|
return;
|
|
1041
1271
|
}
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
error: { code: -32602, message: "Missing context (appInstallationId and workplace required)" }
|
|
1045
|
-
});
|
|
1046
|
-
return;
|
|
1047
|
-
}
|
|
1048
|
-
const installContext = {
|
|
1049
|
-
env: installBody.env ?? {},
|
|
1050
|
-
workplace: installBody.context.workplace,
|
|
1051
|
-
appInstallationId: installBody.context.appInstallationId,
|
|
1052
|
-
app: installBody.context.app,
|
|
1053
|
-
invocation: installBody.invocation,
|
|
1054
|
-
log: createContextLogger()
|
|
1055
|
-
};
|
|
1056
|
-
const installRequestConfig = {
|
|
1057
|
-
baseUrl: installBody.env?.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
|
|
1058
|
-
apiToken: installBody.env?.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
|
|
1059
|
-
};
|
|
1060
|
-
try {
|
|
1061
|
-
const installHook = config.hooks.install;
|
|
1062
|
-
const installHandler = typeof installHook === "function" ? installHook : installHook.handler;
|
|
1063
|
-
const result = await runWithLogContext({ invocation: installBody.invocation }, async () => {
|
|
1064
|
-
return await runWithConfig(installRequestConfig, async () => {
|
|
1065
|
-
return await installHandler(installContext);
|
|
1066
|
-
});
|
|
1067
|
-
});
|
|
1068
|
-
sendJSON(res, 200, {
|
|
1069
|
-
env: result.env ?? {},
|
|
1070
|
-
redirect: result.redirect
|
|
1071
|
-
});
|
|
1072
|
-
} catch (err) {
|
|
1073
|
-
if (err instanceof InstallError) {
|
|
1074
|
-
sendJSON(res, 400, {
|
|
1075
|
-
error: {
|
|
1076
|
-
code: err.code,
|
|
1077
|
-
message: err.message,
|
|
1078
|
-
field: err.field
|
|
1079
|
-
}
|
|
1080
|
-
});
|
|
1081
|
-
} else {
|
|
1082
|
-
sendJSON(res, 500, {
|
|
1083
|
-
error: {
|
|
1084
|
-
code: -32603,
|
|
1085
|
-
message: err instanceof Error ? err.message : String(err ?? "")
|
|
1086
|
-
}
|
|
1087
|
-
});
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1272
|
+
const result = await handleInstall(installBody, config.hooks);
|
|
1273
|
+
sendJSON(res, result.status, result.body);
|
|
1090
1274
|
return;
|
|
1091
1275
|
}
|
|
1092
1276
|
if (pathname === "/uninstall" && req.method === "POST") {
|
|
1093
|
-
if (!config.hooks?.uninstall) {
|
|
1094
|
-
sendJSON(res, 404, { error: "Uninstall handler not configured" });
|
|
1095
|
-
return;
|
|
1096
|
-
}
|
|
1097
1277
|
let uninstallBody;
|
|
1098
1278
|
try {
|
|
1099
1279
|
uninstallBody = await parseJSONBody(req);
|
|
@@ -1103,53 +1283,11 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
|
|
|
1103
1283
|
});
|
|
1104
1284
|
return;
|
|
1105
1285
|
}
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
error: {
|
|
1109
|
-
code: -32602,
|
|
1110
|
-
message: "Missing context (appInstallationId, workplace and app required)"
|
|
1111
|
-
}
|
|
1112
|
-
});
|
|
1113
|
-
return;
|
|
1114
|
-
}
|
|
1115
|
-
const uninstallContext = {
|
|
1116
|
-
env: uninstallBody.env ?? {},
|
|
1117
|
-
workplace: uninstallBody.context.workplace,
|
|
1118
|
-
appInstallationId: uninstallBody.context.appInstallationId,
|
|
1119
|
-
app: uninstallBody.context.app,
|
|
1120
|
-
invocation: uninstallBody.invocation,
|
|
1121
|
-
log: createContextLogger()
|
|
1122
|
-
};
|
|
1123
|
-
const uninstallRequestConfig = {
|
|
1124
|
-
baseUrl: uninstallBody.env?.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
|
|
1125
|
-
apiToken: uninstallBody.env?.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
|
|
1126
|
-
};
|
|
1127
|
-
try {
|
|
1128
|
-
const uninstallHook = config.hooks.uninstall;
|
|
1129
|
-
const uninstallHandlerFn = typeof uninstallHook === "function" ? uninstallHook : uninstallHook.handler;
|
|
1130
|
-
const result = await runWithLogContext({ invocation: uninstallBody.invocation }, async () => {
|
|
1131
|
-
return await runWithConfig(uninstallRequestConfig, async () => {
|
|
1132
|
-
return await uninstallHandlerFn(uninstallContext);
|
|
1133
|
-
});
|
|
1134
|
-
});
|
|
1135
|
-
sendJSON(res, 200, {
|
|
1136
|
-
cleanedWebhookIds: result.cleanedWebhookIds ?? []
|
|
1137
|
-
});
|
|
1138
|
-
} catch (err) {
|
|
1139
|
-
sendJSON(res, 500, {
|
|
1140
|
-
error: {
|
|
1141
|
-
code: -32603,
|
|
1142
|
-
message: err instanceof Error ? err.message : String(err ?? "")
|
|
1143
|
-
}
|
|
1144
|
-
});
|
|
1145
|
-
}
|
|
1286
|
+
const result = await handleUninstall(uninstallBody, config.hooks);
|
|
1287
|
+
sendJSON(res, result.status, result.body);
|
|
1146
1288
|
return;
|
|
1147
1289
|
}
|
|
1148
1290
|
if (pathname === "/provision" && req.method === "POST") {
|
|
1149
|
-
if (!config.hooks?.provision) {
|
|
1150
|
-
sendJSON(res, 404, { error: "Provision handler not configured" });
|
|
1151
|
-
return;
|
|
1152
|
-
}
|
|
1153
1291
|
let provisionBody;
|
|
1154
1292
|
try {
|
|
1155
1293
|
provisionBody = await parseJSONBody(req);
|
|
@@ -1159,46 +1297,8 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
|
|
|
1159
1297
|
});
|
|
1160
1298
|
return;
|
|
1161
1299
|
}
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
error: { code: -32602, message: "Missing context (app required)" }
|
|
1165
|
-
});
|
|
1166
|
-
return;
|
|
1167
|
-
}
|
|
1168
|
-
const mergedEnv = {};
|
|
1169
|
-
for (const [key, value] of Object.entries(process.env)) {
|
|
1170
|
-
if (value !== void 0) {
|
|
1171
|
-
mergedEnv[key] = value;
|
|
1172
|
-
}
|
|
1173
|
-
}
|
|
1174
|
-
Object.assign(mergedEnv, provisionBody.env ?? {});
|
|
1175
|
-
const provisionContext = {
|
|
1176
|
-
env: mergedEnv,
|
|
1177
|
-
app: provisionBody.context.app,
|
|
1178
|
-
invocation: provisionBody.invocation,
|
|
1179
|
-
log: createContextLogger()
|
|
1180
|
-
};
|
|
1181
|
-
const provisionRequestConfig = {
|
|
1182
|
-
baseUrl: mergedEnv.SKEDYUL_API_URL ?? "",
|
|
1183
|
-
apiToken: mergedEnv.SKEDYUL_API_TOKEN ?? ""
|
|
1184
|
-
};
|
|
1185
|
-
try {
|
|
1186
|
-
const provisionHook = config.hooks.provision;
|
|
1187
|
-
const provisionHandler = typeof provisionHook === "function" ? provisionHook : provisionHook.handler;
|
|
1188
|
-
const result = await runWithLogContext({ invocation: provisionBody.invocation }, async () => {
|
|
1189
|
-
return await runWithConfig(provisionRequestConfig, async () => {
|
|
1190
|
-
return await provisionHandler(provisionContext);
|
|
1191
|
-
});
|
|
1192
|
-
});
|
|
1193
|
-
sendJSON(res, 200, result);
|
|
1194
|
-
} catch (err) {
|
|
1195
|
-
sendJSON(res, 500, {
|
|
1196
|
-
error: {
|
|
1197
|
-
code: -32603,
|
|
1198
|
-
message: err instanceof Error ? err.message : String(err ?? "")
|
|
1199
|
-
}
|
|
1200
|
-
});
|
|
1201
|
-
}
|
|
1300
|
+
const result = await handleProvision(provisionBody, config.hooks);
|
|
1301
|
+
sendJSON(res, result.status, result.body);
|
|
1202
1302
|
return;
|
|
1203
1303
|
}
|
|
1204
1304
|
if (pathname === "/core" && req.method === "POST") {
|
|
@@ -1379,12 +1479,10 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer) {
|
|
|
1379
1479
|
}
|
|
1380
1480
|
if (path.startsWith("/webhooks/") && webhookRegistry) {
|
|
1381
1481
|
const handle = path.slice("/webhooks/".length);
|
|
1382
|
-
|
|
1383
|
-
if (!webhookDef) {
|
|
1482
|
+
if (!webhookRegistry[handle]) {
|
|
1384
1483
|
return createResponse(404, { error: `Webhook handler '${handle}' not found` }, headers);
|
|
1385
1484
|
}
|
|
1386
|
-
|
|
1387
|
-
if (!allowedMethods.includes(method)) {
|
|
1485
|
+
if (!isMethodAllowed(webhookRegistry, handle, method)) {
|
|
1388
1486
|
return createResponse(405, { error: `Method ${method} not allowed` }, headers);
|
|
1389
1487
|
}
|
|
1390
1488
|
const rawBody = event.body ?? "";
|
|
@@ -1399,107 +1497,34 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer) {
|
|
|
1399
1497
|
} else {
|
|
1400
1498
|
parsedBody = rawBody;
|
|
1401
1499
|
}
|
|
1402
|
-
const
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
method: envelope.request.method,
|
|
1421
|
-
url: envelope.request.url,
|
|
1422
|
-
path: envelope.request.path,
|
|
1423
|
-
headers: envelope.request.headers,
|
|
1424
|
-
query: envelope.request.query,
|
|
1425
|
-
body: originalParsedBody,
|
|
1426
|
-
rawBody: envelope.request.body ? Buffer.from(envelope.request.body, "utf-8") : void 0
|
|
1427
|
-
};
|
|
1428
|
-
const envVars = { ...process.env, ...requestEnv };
|
|
1429
|
-
const app = envelope.context.app;
|
|
1430
|
-
if (envelope.context.appInstallationId && envelope.context.workplace) {
|
|
1431
|
-
webhookContext = {
|
|
1432
|
-
env: envVars,
|
|
1433
|
-
app,
|
|
1434
|
-
appInstallationId: envelope.context.appInstallationId,
|
|
1435
|
-
workplace: envelope.context.workplace,
|
|
1436
|
-
registration: envelope.context.registration ?? {},
|
|
1437
|
-
invocation,
|
|
1438
|
-
log: createContextLogger()
|
|
1439
|
-
};
|
|
1440
|
-
} else {
|
|
1441
|
-
webhookContext = {
|
|
1442
|
-
env: envVars,
|
|
1443
|
-
app,
|
|
1444
|
-
invocation,
|
|
1445
|
-
log: createContextLogger()
|
|
1446
|
-
};
|
|
1447
|
-
}
|
|
1448
|
-
} else {
|
|
1449
|
-
const appId = event.headers?.["x-skedyul-app-id"] ?? event.headers?.["X-Skedyul-App-Id"];
|
|
1450
|
-
const appVersionId = event.headers?.["x-skedyul-app-version-id"] ?? event.headers?.["X-Skedyul-App-Version-Id"];
|
|
1451
|
-
if (!appId || !appVersionId) {
|
|
1452
|
-
throw new Error("Missing app info in webhook request (x-skedyul-app-id and x-skedyul-app-version-id headers required)");
|
|
1453
|
-
}
|
|
1454
|
-
const forwardedProto = event.headers?.["x-forwarded-proto"] ?? event.headers?.["X-Forwarded-Proto"];
|
|
1455
|
-
const protocol = forwardedProto ?? "https";
|
|
1456
|
-
const host = event.headers?.host ?? event.headers?.Host ?? "localhost";
|
|
1457
|
-
const queryString = event.queryStringParameters ? "?" + new URLSearchParams(event.queryStringParameters).toString() : "";
|
|
1458
|
-
const webhookUrl = `${protocol}://${host}${path}${queryString}`;
|
|
1459
|
-
webhookRequest = {
|
|
1460
|
-
method,
|
|
1461
|
-
url: webhookUrl,
|
|
1462
|
-
path,
|
|
1463
|
-
headers: event.headers,
|
|
1464
|
-
query: event.queryStringParameters ?? {},
|
|
1465
|
-
body: parsedBody,
|
|
1466
|
-
rawBody: rawBody ? Buffer.from(rawBody, "utf-8") : void 0
|
|
1467
|
-
};
|
|
1468
|
-
webhookContext = {
|
|
1469
|
-
env: process.env,
|
|
1470
|
-
app: { id: appId, versionId: appVersionId },
|
|
1471
|
-
log: createContextLogger()
|
|
1472
|
-
};
|
|
1473
|
-
}
|
|
1474
|
-
const originalEnv = { ...process.env };
|
|
1475
|
-
Object.assign(process.env, requestEnv);
|
|
1476
|
-
const requestConfig = {
|
|
1477
|
-
baseUrl: requestEnv.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
|
|
1478
|
-
apiToken: requestEnv.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
|
|
1479
|
-
};
|
|
1480
|
-
let webhookResponse;
|
|
1481
|
-
try {
|
|
1482
|
-
webhookResponse = await runWithLogContext({ invocation }, async () => {
|
|
1483
|
-
return await runWithConfig(requestConfig, async () => {
|
|
1484
|
-
return await webhookDef.handler(webhookRequest, webhookContext);
|
|
1485
|
-
});
|
|
1486
|
-
});
|
|
1487
|
-
} catch (err) {
|
|
1488
|
-
console.error(`Webhook handler '${handle}' error:`, err);
|
|
1489
|
-
return createResponse(500, { error: "Webhook handler error" }, headers);
|
|
1490
|
-
} finally {
|
|
1491
|
-
process.env = originalEnv;
|
|
1500
|
+
const forwardedProto = event.headers?.["x-forwarded-proto"] ?? event.headers?.["X-Forwarded-Proto"];
|
|
1501
|
+
const protocol = forwardedProto ?? "https";
|
|
1502
|
+
const host = event.headers?.host ?? event.headers?.Host ?? "localhost";
|
|
1503
|
+
const queryString = event.queryStringParameters ? "?" + new URLSearchParams(event.queryStringParameters).toString() : "";
|
|
1504
|
+
const webhookUrl = `${protocol}://${host}${path}${queryString}`;
|
|
1505
|
+
const parseResult = parseWebhookRequest(
|
|
1506
|
+
parsedBody,
|
|
1507
|
+
method,
|
|
1508
|
+
webhookUrl,
|
|
1509
|
+
path,
|
|
1510
|
+
event.headers,
|
|
1511
|
+
event.queryStringParameters ?? {},
|
|
1512
|
+
rawBody,
|
|
1513
|
+
event.headers?.["x-skedyul-app-id"] ?? event.headers?.["X-Skedyul-App-Id"],
|
|
1514
|
+
event.headers?.["x-skedyul-app-version-id"] ?? event.headers?.["X-Skedyul-App-Version-Id"]
|
|
1515
|
+
);
|
|
1516
|
+
if ("error" in parseResult) {
|
|
1517
|
+
return createResponse(400, { error: parseResult.error }, headers);
|
|
1492
1518
|
}
|
|
1519
|
+
const result = await executeWebhookHandler(handle, webhookRegistry, parseResult);
|
|
1493
1520
|
const responseHeaders = {
|
|
1494
1521
|
...headers,
|
|
1495
|
-
...
|
|
1522
|
+
...result.headers
|
|
1496
1523
|
};
|
|
1497
|
-
const status = webhookResponse.status ?? 200;
|
|
1498
|
-
const body = webhookResponse.body;
|
|
1499
1524
|
return {
|
|
1500
|
-
statusCode: status,
|
|
1525
|
+
statusCode: result.status,
|
|
1501
1526
|
headers: responseHeaders,
|
|
1502
|
-
body: body !== void 0 ? typeof body === "string" ? body : JSON.stringify(body) : ""
|
|
1527
|
+
body: result.body !== void 0 ? typeof result.body === "string" ? result.body : JSON.stringify(result.body) : ""
|
|
1503
1528
|
};
|
|
1504
1529
|
}
|
|
1505
1530
|
if (path === "/core" && method === "POST") {
|
|
@@ -1635,9 +1660,6 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer) {
|
|
|
1635
1660
|
}
|
|
1636
1661
|
}
|
|
1637
1662
|
if (path === "/install" && method === "POST") {
|
|
1638
|
-
if (!config.hooks?.install) {
|
|
1639
|
-
return createResponse(404, { error: "Install handler not configured" }, headers);
|
|
1640
|
-
}
|
|
1641
1663
|
let installBody;
|
|
1642
1664
|
try {
|
|
1643
1665
|
installBody = event.body ? JSON.parse(event.body) : {};
|
|
@@ -1648,68 +1670,10 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer) {
|
|
|
1648
1670
|
headers
|
|
1649
1671
|
);
|
|
1650
1672
|
}
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
400,
|
|
1654
|
-
{ error: { code: -32602, message: "Missing context (appInstallationId and workplace required)" } },
|
|
1655
|
-
headers
|
|
1656
|
-
);
|
|
1657
|
-
}
|
|
1658
|
-
const installContext = {
|
|
1659
|
-
env: installBody.env ?? {},
|
|
1660
|
-
workplace: installBody.context.workplace,
|
|
1661
|
-
appInstallationId: installBody.context.appInstallationId,
|
|
1662
|
-
app: installBody.context.app,
|
|
1663
|
-
invocation: installBody.invocation,
|
|
1664
|
-
log: createContextLogger()
|
|
1665
|
-
};
|
|
1666
|
-
const installRequestConfig = {
|
|
1667
|
-
baseUrl: installBody.env?.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
|
|
1668
|
-
apiToken: installBody.env?.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
|
|
1669
|
-
};
|
|
1670
|
-
try {
|
|
1671
|
-
const installHook = config.hooks.install;
|
|
1672
|
-
const installHandler = typeof installHook === "function" ? installHook : installHook.handler;
|
|
1673
|
-
const result = await runWithLogContext({ invocation: installBody.invocation }, async () => {
|
|
1674
|
-
return await runWithConfig(installRequestConfig, async () => {
|
|
1675
|
-
return await installHandler(installContext);
|
|
1676
|
-
});
|
|
1677
|
-
});
|
|
1678
|
-
return createResponse(
|
|
1679
|
-
200,
|
|
1680
|
-
{ env: result.env ?? {}, redirect: result.redirect },
|
|
1681
|
-
headers
|
|
1682
|
-
);
|
|
1683
|
-
} catch (err) {
|
|
1684
|
-
if (err instanceof InstallError) {
|
|
1685
|
-
return createResponse(
|
|
1686
|
-
400,
|
|
1687
|
-
{
|
|
1688
|
-
error: {
|
|
1689
|
-
code: err.code,
|
|
1690
|
-
message: err.message,
|
|
1691
|
-
field: err.field
|
|
1692
|
-
}
|
|
1693
|
-
},
|
|
1694
|
-
headers
|
|
1695
|
-
);
|
|
1696
|
-
}
|
|
1697
|
-
return createResponse(
|
|
1698
|
-
500,
|
|
1699
|
-
{
|
|
1700
|
-
error: {
|
|
1701
|
-
code: -32603,
|
|
1702
|
-
message: err instanceof Error ? err.message : String(err ?? "")
|
|
1703
|
-
}
|
|
1704
|
-
},
|
|
1705
|
-
headers
|
|
1706
|
-
);
|
|
1707
|
-
}
|
|
1673
|
+
const result = await handleInstall(installBody, config.hooks);
|
|
1674
|
+
return createResponse(result.status, result.body, headers);
|
|
1708
1675
|
}
|
|
1709
1676
|
if (path === "/uninstall" && method === "POST") {
|
|
1710
|
-
if (!config.hooks?.uninstall) {
|
|
1711
|
-
return createResponse(404, { error: "Uninstall handler not configured" }, headers);
|
|
1712
|
-
}
|
|
1713
1677
|
let uninstallBody;
|
|
1714
1678
|
try {
|
|
1715
1679
|
uninstallBody = event.body ? JSON.parse(event.body) : {};
|
|
@@ -1720,137 +1684,24 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer) {
|
|
|
1720
1684
|
headers
|
|
1721
1685
|
);
|
|
1722
1686
|
}
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
400,
|
|
1726
|
-
{
|
|
1727
|
-
error: {
|
|
1728
|
-
code: -32602,
|
|
1729
|
-
message: "Missing context (appInstallationId, workplace and app required)"
|
|
1730
|
-
}
|
|
1731
|
-
},
|
|
1732
|
-
headers
|
|
1733
|
-
);
|
|
1734
|
-
}
|
|
1735
|
-
const uninstallContext = {
|
|
1736
|
-
env: uninstallBody.env ?? {},
|
|
1737
|
-
workplace: uninstallBody.context.workplace,
|
|
1738
|
-
appInstallationId: uninstallBody.context.appInstallationId,
|
|
1739
|
-
app: uninstallBody.context.app,
|
|
1740
|
-
invocation: uninstallBody.invocation,
|
|
1741
|
-
log: createContextLogger()
|
|
1742
|
-
};
|
|
1743
|
-
const uninstallRequestConfig = {
|
|
1744
|
-
baseUrl: uninstallBody.env?.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
|
|
1745
|
-
apiToken: uninstallBody.env?.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
|
|
1746
|
-
};
|
|
1747
|
-
try {
|
|
1748
|
-
const uninstallHook = config.hooks.uninstall;
|
|
1749
|
-
const uninstallHandlerFn = typeof uninstallHook === "function" ? uninstallHook : uninstallHook.handler;
|
|
1750
|
-
const result = await runWithLogContext({ invocation: uninstallBody.invocation }, async () => {
|
|
1751
|
-
return await runWithConfig(uninstallRequestConfig, async () => {
|
|
1752
|
-
return await uninstallHandlerFn(uninstallContext);
|
|
1753
|
-
});
|
|
1754
|
-
});
|
|
1755
|
-
return createResponse(
|
|
1756
|
-
200,
|
|
1757
|
-
{ cleanedWebhookIds: result.cleanedWebhookIds ?? [] },
|
|
1758
|
-
headers
|
|
1759
|
-
);
|
|
1760
|
-
} catch (err) {
|
|
1761
|
-
return createResponse(
|
|
1762
|
-
500,
|
|
1763
|
-
{
|
|
1764
|
-
error: {
|
|
1765
|
-
code: -32603,
|
|
1766
|
-
message: err instanceof Error ? err.message : String(err ?? "")
|
|
1767
|
-
}
|
|
1768
|
-
},
|
|
1769
|
-
headers
|
|
1770
|
-
);
|
|
1771
|
-
}
|
|
1687
|
+
const result = await handleUninstall(uninstallBody, config.hooks);
|
|
1688
|
+
return createResponse(result.status, result.body, headers);
|
|
1772
1689
|
}
|
|
1773
1690
|
if (path === "/provision" && method === "POST") {
|
|
1774
|
-
console.log("[serverless] /provision endpoint called");
|
|
1775
|
-
if (!config.hooks?.provision) {
|
|
1776
|
-
console.log("[serverless] No provision handler configured");
|
|
1777
|
-
return createResponse(404, { error: "Provision handler not configured" }, headers);
|
|
1778
|
-
}
|
|
1779
1691
|
let provisionBody;
|
|
1780
1692
|
try {
|
|
1781
1693
|
provisionBody = event.body ? JSON.parse(event.body) : {};
|
|
1782
|
-
console.log("[serverless] Provision body parsed:", {
|
|
1783
|
-
hasEnv: !!provisionBody.env,
|
|
1784
|
-
hasContext: !!provisionBody.context,
|
|
1785
|
-
appId: provisionBody.context?.app?.id,
|
|
1786
|
-
versionId: provisionBody.context?.app?.versionId
|
|
1787
|
-
});
|
|
1788
1694
|
} catch {
|
|
1789
|
-
console.log("[serverless] Failed to parse provision body");
|
|
1790
1695
|
return createResponse(
|
|
1791
1696
|
400,
|
|
1792
1697
|
{ error: { code: -32700, message: "Parse error" } },
|
|
1793
1698
|
headers
|
|
1794
1699
|
);
|
|
1795
1700
|
}
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
return createResponse(
|
|
1799
|
-
400,
|
|
1800
|
-
{ error: { code: -32602, message: "Missing context (app required)" } },
|
|
1801
|
-
headers
|
|
1802
|
-
);
|
|
1803
|
-
}
|
|
1804
|
-
const mergedEnv = {};
|
|
1805
|
-
for (const [key, value] of Object.entries(process.env)) {
|
|
1806
|
-
if (value !== void 0) {
|
|
1807
|
-
mergedEnv[key] = value;
|
|
1808
|
-
}
|
|
1809
|
-
}
|
|
1810
|
-
Object.assign(mergedEnv, provisionBody.env ?? {});
|
|
1811
|
-
const provisionContext = {
|
|
1812
|
-
env: mergedEnv,
|
|
1813
|
-
app: provisionBody.context.app,
|
|
1814
|
-
invocation: provisionBody.invocation,
|
|
1815
|
-
log: createContextLogger()
|
|
1816
|
-
};
|
|
1817
|
-
const provisionRequestConfig = {
|
|
1818
|
-
baseUrl: mergedEnv.SKEDYUL_API_URL ?? "",
|
|
1819
|
-
apiToken: mergedEnv.SKEDYUL_API_TOKEN ?? ""
|
|
1820
|
-
};
|
|
1821
|
-
console.log("[serverless] Calling provision handler...");
|
|
1822
|
-
try {
|
|
1823
|
-
const provisionHook = config.hooks.provision;
|
|
1824
|
-
const provisionHandler = typeof provisionHook === "function" ? provisionHook : provisionHook.handler;
|
|
1825
|
-
const result = await runWithLogContext({ invocation: provisionBody.invocation }, async () => {
|
|
1826
|
-
return await runWithConfig(provisionRequestConfig, async () => {
|
|
1827
|
-
return await provisionHandler(provisionContext);
|
|
1828
|
-
});
|
|
1829
|
-
});
|
|
1830
|
-
console.log("[serverless] Provision handler completed successfully");
|
|
1831
|
-
return createResponse(200, result, headers);
|
|
1832
|
-
} catch (err) {
|
|
1833
|
-
console.error("[serverless] Provision handler failed:", err instanceof Error ? err.message : String(err));
|
|
1834
|
-
return createResponse(
|
|
1835
|
-
500,
|
|
1836
|
-
{
|
|
1837
|
-
error: {
|
|
1838
|
-
code: -32603,
|
|
1839
|
-
message: err instanceof Error ? err.message : String(err ?? "")
|
|
1840
|
-
}
|
|
1841
|
-
},
|
|
1842
|
-
headers
|
|
1843
|
-
);
|
|
1844
|
-
}
|
|
1701
|
+
const result = await handleProvision(provisionBody, config.hooks);
|
|
1702
|
+
return createResponse(result.status, result.body, headers);
|
|
1845
1703
|
}
|
|
1846
1704
|
if (path === "/oauth_callback" && method === "POST") {
|
|
1847
|
-
if (!config.hooks?.oauth_callback) {
|
|
1848
|
-
return createResponse(
|
|
1849
|
-
404,
|
|
1850
|
-
{ error: "OAuth callback handler not configured" },
|
|
1851
|
-
headers
|
|
1852
|
-
);
|
|
1853
|
-
}
|
|
1854
1705
|
let parsedBody;
|
|
1855
1706
|
try {
|
|
1856
1707
|
parsedBody = event.body ? JSON.parse(event.body) : {};
|
|
@@ -1862,52 +1713,8 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer) {
|
|
|
1862
1713
|
headers
|
|
1863
1714
|
);
|
|
1864
1715
|
}
|
|
1865
|
-
const
|
|
1866
|
-
|
|
1867
|
-
console.error("[OAuth Callback] Failed to parse envelope. Body:", JSON.stringify(parsedBody, null, 2));
|
|
1868
|
-
return createResponse(
|
|
1869
|
-
400,
|
|
1870
|
-
{ error: { code: -32602, message: "Missing envelope format: expected { env, request }" } },
|
|
1871
|
-
headers
|
|
1872
|
-
);
|
|
1873
|
-
}
|
|
1874
|
-
const invocation = parsedBody.invocation;
|
|
1875
|
-
const oauthRequest = buildRequestFromRaw(envelope.request);
|
|
1876
|
-
const oauthCallbackRequestConfig = buildRequestScopedConfig(envelope.env);
|
|
1877
|
-
const oauthCallbackContext = {
|
|
1878
|
-
request: oauthRequest,
|
|
1879
|
-
invocation,
|
|
1880
|
-
log: createContextLogger()
|
|
1881
|
-
};
|
|
1882
|
-
try {
|
|
1883
|
-
const oauthCallbackHook = config.hooks.oauth_callback;
|
|
1884
|
-
const oauthCallbackHandler = typeof oauthCallbackHook === "function" ? oauthCallbackHook : oauthCallbackHook.handler;
|
|
1885
|
-
const result = await runWithLogContext({ invocation }, async () => {
|
|
1886
|
-
return await runWithConfig(oauthCallbackRequestConfig, async () => {
|
|
1887
|
-
return await oauthCallbackHandler(oauthCallbackContext);
|
|
1888
|
-
});
|
|
1889
|
-
});
|
|
1890
|
-
return createResponse(
|
|
1891
|
-
200,
|
|
1892
|
-
{
|
|
1893
|
-
appInstallationId: result.appInstallationId,
|
|
1894
|
-
env: result.env ?? {}
|
|
1895
|
-
},
|
|
1896
|
-
headers
|
|
1897
|
-
);
|
|
1898
|
-
} catch (err) {
|
|
1899
|
-
const errorMessage = err instanceof Error ? err.message : String(err ?? "Unknown error");
|
|
1900
|
-
return createResponse(
|
|
1901
|
-
500,
|
|
1902
|
-
{
|
|
1903
|
-
error: {
|
|
1904
|
-
code: -32603,
|
|
1905
|
-
message: errorMessage
|
|
1906
|
-
}
|
|
1907
|
-
},
|
|
1908
|
-
headers
|
|
1909
|
-
);
|
|
1910
|
-
}
|
|
1716
|
+
const result = await handleOAuthCallback(parsedBody, config.hooks);
|
|
1717
|
+
return createResponse(result.status, result.body, headers);
|
|
1911
1718
|
}
|
|
1912
1719
|
if (path === "/health" && method === "GET") {
|
|
1913
1720
|
return createResponse(200, state.getHealthStatus(), headers);
|
|
@@ -2302,32 +2109,10 @@ var server = {
|
|
|
2302
2109
|
};
|
|
2303
2110
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2304
2111
|
0 && (module.exports = {
|
|
2305
|
-
buildRequestFromRaw,
|
|
2306
|
-
buildRequestScopedConfig,
|
|
2307
|
-
buildToolMetadata,
|
|
2308
|
-
createCallToolHandler,
|
|
2309
|
-
createDedicatedServerInstance,
|
|
2310
|
-
createRequestState,
|
|
2311
|
-
createResponse,
|
|
2312
|
-
createServerlessInstance,
|
|
2313
2112
|
createSkedyulServer,
|
|
2314
|
-
getDefaultHeaders,
|
|
2315
2113
|
getJsonSchemaFromToolSchema,
|
|
2316
|
-
getListeningPort,
|
|
2317
2114
|
getZodSchema,
|
|
2318
|
-
handleCoreMethod,
|
|
2319
2115
|
isToolSchemaWithJson,
|
|
2320
|
-
mergeRuntimeEnv,
|
|
2321
|
-
normalizeBilling,
|
|
2322
|
-
padEnd,
|
|
2323
|
-
parseHandlerEnvelope,
|
|
2324
|
-
parseJSONBody,
|
|
2325
|
-
parseJsonRecord,
|
|
2326
|
-
parseNumberEnv,
|
|
2327
|
-
printStartupLog,
|
|
2328
|
-
readRawRequestBody,
|
|
2329
|
-
sendHTML,
|
|
2330
|
-
sendJSON,
|
|
2331
2116
|
server,
|
|
2332
2117
|
toJsonSchema
|
|
2333
2118
|
});
|