skedyul 0.3.0 → 0.3.2

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.
Files changed (77) hide show
  1. package/dist/.build-stamp +1 -1
  2. package/dist/config/app-config.d.ts +73 -0
  3. package/dist/config/app-config.js +12 -0
  4. package/dist/config/index.d.ts +9 -0
  5. package/dist/config/index.js +33 -0
  6. package/dist/config/loader.d.ts +7 -0
  7. package/dist/config/loader.js +119 -0
  8. package/dist/config/types/agent.d.ts +29 -0
  9. package/dist/config/types/agent.js +5 -0
  10. package/dist/config/types/channel.d.ts +46 -0
  11. package/dist/config/types/channel.js +2 -0
  12. package/dist/config/types/compute.d.ts +1 -0
  13. package/dist/config/types/compute.js +5 -0
  14. package/dist/config/types/env.d.ts +16 -0
  15. package/dist/config/types/env.js +5 -0
  16. package/dist/config/types/index.d.ts +9 -0
  17. package/dist/config/types/index.js +26 -0
  18. package/dist/config/types/model.d.ts +62 -0
  19. package/dist/config/types/model.js +2 -0
  20. package/dist/config/types/page.d.ts +436 -0
  21. package/dist/config/types/page.js +5 -0
  22. package/dist/config/types/resource.d.ts +30 -0
  23. package/dist/config/types/resource.js +5 -0
  24. package/dist/config/types/webhook.d.ts +35 -0
  25. package/dist/config/types/webhook.js +5 -0
  26. package/dist/config/types/workflow.d.ts +24 -0
  27. package/dist/config/types/workflow.js +2 -0
  28. package/dist/config/utils.d.ts +16 -0
  29. package/dist/config/utils.js +37 -0
  30. package/dist/config.d.ts +5 -767
  31. package/dist/config.js +11 -151
  32. package/dist/schemas.d.ts +43 -43
  33. package/dist/server/core-api-handler.d.ts +8 -0
  34. package/dist/server/core-api-handler.js +148 -0
  35. package/dist/server/dedicated.d.ts +7 -0
  36. package/dist/server/dedicated.js +610 -0
  37. package/dist/server/handler-helpers.d.ts +24 -0
  38. package/dist/server/handler-helpers.js +75 -0
  39. package/dist/server/index.d.ts +19 -0
  40. package/dist/server/index.js +196 -0
  41. package/dist/server/serverless.d.ts +7 -0
  42. package/dist/server/serverless.js +629 -0
  43. package/dist/server/startup-logger.d.ts +9 -0
  44. package/dist/server/startup-logger.js +113 -0
  45. package/dist/server/tool-handler.d.ts +14 -0
  46. package/dist/server/tool-handler.js +189 -0
  47. package/dist/server/types.d.ts +22 -0
  48. package/dist/server/types.js +2 -0
  49. package/dist/server/utils/env.d.ts +12 -0
  50. package/dist/server/utils/env.js +38 -0
  51. package/dist/server/utils/http.d.ts +30 -0
  52. package/dist/server/utils/http.js +81 -0
  53. package/dist/server/utils/index.d.ts +3 -0
  54. package/dist/server/utils/index.js +24 -0
  55. package/dist/server/utils/schema.d.ts +22 -0
  56. package/dist/server/utils/schema.js +102 -0
  57. package/dist/server.d.ts +7 -11
  58. package/dist/server.js +39 -2026
  59. package/dist/types/aws.d.ts +15 -0
  60. package/dist/types/aws.js +5 -0
  61. package/dist/types/handlers.d.ts +122 -0
  62. package/dist/types/handlers.js +2 -0
  63. package/dist/types/index.d.ts +16 -0
  64. package/dist/types/index.js +16 -0
  65. package/dist/types/server.d.ts +43 -0
  66. package/dist/types/server.js +2 -0
  67. package/dist/types/shared.d.ts +16 -0
  68. package/dist/types/shared.js +5 -0
  69. package/dist/types/tool-context.d.ts +64 -0
  70. package/dist/types/tool-context.js +12 -0
  71. package/dist/types/tool.d.ts +96 -0
  72. package/dist/types/tool.js +19 -0
  73. package/dist/types/webhook.d.ts +116 -0
  74. package/dist/types/webhook.js +7 -0
  75. package/dist/types.d.ts +4 -461
  76. package/dist/types.js +21 -31
  77. package/package.json +2 -2
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.padEnd = padEnd;
4
+ exports.printStartupLog = printStartupLog;
5
+ const utils_1 = require("./utils");
6
+ /**
7
+ * Pad a string to the right with spaces
8
+ */
9
+ function padEnd(str, length) {
10
+ if (str.length >= length) {
11
+ return str.slice(0, length);
12
+ }
13
+ return str + ' '.repeat(length - str.length);
14
+ }
15
+ /**
16
+ * Prints a styled startup log showing server configuration
17
+ */
18
+ function printStartupLog(config, tools, webhookRegistry, port) {
19
+ // Skip startup log during tests
20
+ if (process.env.NODE_ENV === 'test') {
21
+ return;
22
+ }
23
+ const webhookCount = webhookRegistry ? Object.keys(webhookRegistry).length : 0;
24
+ const webhookNames = webhookRegistry ? Object.keys(webhookRegistry) : [];
25
+ const maxRequests = config.maxRequests ??
26
+ (0, utils_1.parseNumberEnv)(process.env.MCP_MAX_REQUESTS) ??
27
+ null;
28
+ const ttlExtendSeconds = config.ttlExtendSeconds ??
29
+ (0, utils_1.parseNumberEnv)(process.env.MCP_TTL_EXTEND) ??
30
+ 3600;
31
+ const executableId = process.env.SKEDYUL_EXECUTABLE_ID || 'local';
32
+ const divider = '═'.repeat(70);
33
+ const thinDivider = '─'.repeat(70);
34
+ // eslint-disable-next-line no-console
35
+ console.log('');
36
+ // eslint-disable-next-line no-console
37
+ console.log(`╔${divider}╗`);
38
+ // eslint-disable-next-line no-console
39
+ console.log(`║ 🚀 Skedyul MCP Server Starting ║`);
40
+ // eslint-disable-next-line no-console
41
+ console.log(`╠${divider}╣`);
42
+ // eslint-disable-next-line no-console
43
+ console.log(`║ ║`);
44
+ // eslint-disable-next-line no-console
45
+ console.log(`║ 📦 Server: ${padEnd(config.metadata.name, 49)}║`);
46
+ // eslint-disable-next-line no-console
47
+ console.log(`║ 🏷️ Version: ${padEnd(config.metadata.version, 49)}║`);
48
+ // eslint-disable-next-line no-console
49
+ console.log(`║ ⚡ Compute: ${padEnd(config.computeLayer, 49)}║`);
50
+ if (port) {
51
+ // eslint-disable-next-line no-console
52
+ console.log(`║ 🌐 Port: ${padEnd(String(port), 49)}║`);
53
+ }
54
+ // eslint-disable-next-line no-console
55
+ console.log(`║ 🔑 Executable: ${padEnd(executableId, 49)}║`);
56
+ // eslint-disable-next-line no-console
57
+ console.log(`║ ║`);
58
+ // eslint-disable-next-line no-console
59
+ console.log(`╟${thinDivider}╢`);
60
+ // eslint-disable-next-line no-console
61
+ console.log(`║ ║`);
62
+ // eslint-disable-next-line no-console
63
+ console.log(`║ 🔧 Tools (${tools.length}): ║`);
64
+ // List tools (max 10, then show "and X more...")
65
+ const maxToolsToShow = 10;
66
+ const toolsToShow = tools.slice(0, maxToolsToShow);
67
+ for (const tool of toolsToShow) {
68
+ // eslint-disable-next-line no-console
69
+ console.log(`║ • ${padEnd(tool.name, 61)}║`);
70
+ }
71
+ if (tools.length > maxToolsToShow) {
72
+ // eslint-disable-next-line no-console
73
+ console.log(`║ ... and ${tools.length - maxToolsToShow} more ║`);
74
+ }
75
+ if (webhookCount > 0) {
76
+ // eslint-disable-next-line no-console
77
+ console.log(`║ ║`);
78
+ // eslint-disable-next-line no-console
79
+ console.log(`║ 🪝 Webhooks (${webhookCount}): ║`);
80
+ const maxWebhooksToShow = 5;
81
+ const webhooksToShow = webhookNames.slice(0, maxWebhooksToShow);
82
+ for (const name of webhooksToShow) {
83
+ // eslint-disable-next-line no-console
84
+ console.log(`║ • /webhooks/${padEnd(name, 51)}║`);
85
+ }
86
+ if (webhookCount > maxWebhooksToShow) {
87
+ // eslint-disable-next-line no-console
88
+ console.log(`║ ... and ${webhookCount - maxWebhooksToShow} more ║`);
89
+ }
90
+ }
91
+ // eslint-disable-next-line no-console
92
+ console.log(`║ ║`);
93
+ // eslint-disable-next-line no-console
94
+ console.log(`╟${thinDivider}╢`);
95
+ // eslint-disable-next-line no-console
96
+ console.log(`║ ║`);
97
+ // eslint-disable-next-line no-console
98
+ console.log(`║ ⚙️ Configuration: ║`);
99
+ // eslint-disable-next-line no-console
100
+ console.log(`║ Max Requests: ${padEnd(maxRequests !== null ? String(maxRequests) : 'unlimited', 46)}║`);
101
+ // eslint-disable-next-line no-console
102
+ console.log(`║ TTL Extend: ${padEnd(`${ttlExtendSeconds}s`, 46)}║`);
103
+ // eslint-disable-next-line no-console
104
+ console.log(`║ ║`);
105
+ // eslint-disable-next-line no-console
106
+ console.log(`╟${thinDivider}╢`);
107
+ // eslint-disable-next-line no-console
108
+ console.log(`║ ✅ Ready at ${padEnd(new Date().toISOString(), 55)}║`);
109
+ // eslint-disable-next-line no-console
110
+ console.log(`╚${divider}╝`);
111
+ // eslint-disable-next-line no-console
112
+ console.log('');
113
+ }
@@ -0,0 +1,14 @@
1
+ import type { ToolCallResponse, ToolMetadata, ToolRegistry } from '../types';
2
+ import type { RequestState } from './types';
3
+ /**
4
+ * Builds tool metadata array from a tool registry
5
+ */
6
+ export declare function buildToolMetadata(registry: ToolRegistry): ToolMetadata[];
7
+ /**
8
+ * Creates a request state tracker for managing request counts and health status
9
+ */
10
+ export declare function createRequestState(maxRequests: number | null, ttlExtendSeconds: number, runtimeLabel: string, toolNames: string[]): RequestState;
11
+ /**
12
+ * Creates a tool call handler function for executing tools from the registry
13
+ */
14
+ export declare function createCallToolHandler<T extends ToolRegistry>(registry: T, state: RequestState, onMaxRequests?: () => void): (nameRaw: unknown, argsRaw: unknown) => Promise<ToolCallResponse>;
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildToolMetadata = buildToolMetadata;
4
+ exports.createRequestState = createRequestState;
5
+ exports.createCallToolHandler = createCallToolHandler;
6
+ const utils_1 = require("./utils");
7
+ const client_1 = require("../core/client");
8
+ const errors_1 = require("../errors");
9
+ /**
10
+ * Builds tool metadata array from a tool registry
11
+ */
12
+ function buildToolMetadata(registry) {
13
+ return Object.values(registry).map((tool) => {
14
+ const timeout = typeof tool.timeout === 'number' && tool.timeout > 0 ? tool.timeout : 10000;
15
+ return {
16
+ name: tool.name,
17
+ displayName: tool.label || tool.name,
18
+ description: tool.description,
19
+ inputSchema: (0, utils_1.getJsonSchemaFromToolSchema)(tool.inputSchema),
20
+ outputSchema: (0, utils_1.getJsonSchemaFromToolSchema)(tool.outputSchema),
21
+ timeout, // Default to 10 seconds
22
+ };
23
+ });
24
+ }
25
+ /**
26
+ * Creates a request state tracker for managing request counts and health status
27
+ */
28
+ function createRequestState(maxRequests, ttlExtendSeconds, runtimeLabel, toolNames) {
29
+ let requestCount = 0;
30
+ let lastRequestTime = Date.now();
31
+ return {
32
+ incrementRequestCount() {
33
+ requestCount += 1;
34
+ lastRequestTime = Date.now();
35
+ },
36
+ shouldShutdown() {
37
+ return maxRequests !== null && requestCount >= maxRequests;
38
+ },
39
+ getHealthStatus() {
40
+ return {
41
+ status: 'running',
42
+ requests: requestCount,
43
+ maxRequests,
44
+ requestsRemaining: maxRequests !== null ? Math.max(0, maxRequests - requestCount) : null,
45
+ lastRequestTime,
46
+ ttlExtendSeconds,
47
+ runtime: runtimeLabel,
48
+ tools: [...toolNames],
49
+ };
50
+ },
51
+ };
52
+ }
53
+ /**
54
+ * Creates a tool call handler function for executing tools from the registry
55
+ */
56
+ function createCallToolHandler(registry, state, onMaxRequests) {
57
+ return async function callTool(nameRaw, argsRaw) {
58
+ const toolName = String(nameRaw);
59
+ const tool = registry[toolName];
60
+ if (!tool) {
61
+ throw new Error(`Tool "${toolName}" not found in registry`);
62
+ }
63
+ if (!tool.handler || typeof tool.handler !== 'function') {
64
+ throw new Error(`Tool "${toolName}" handler is not a function`);
65
+ }
66
+ const fn = tool.handler;
67
+ const args = (argsRaw ?? {});
68
+ const estimateMode = args.estimate === true;
69
+ if (!estimateMode) {
70
+ state.incrementRequestCount();
71
+ if (state.shouldShutdown()) {
72
+ onMaxRequests?.();
73
+ }
74
+ }
75
+ const requestEnv = args.env ?? {};
76
+ const originalEnv = { ...process.env };
77
+ Object.assign(process.env, requestEnv);
78
+ try {
79
+ // Get tool inputs (clean, no context)
80
+ const inputs = (args.inputs ?? {});
81
+ // Get context from args.context (separate from inputs)
82
+ const rawContext = (args.context ?? {});
83
+ // Extract app info (required for all contexts)
84
+ const app = rawContext.app;
85
+ // Determine trigger type from context
86
+ const trigger = rawContext.trigger || 'agent';
87
+ // Build execution context based on trigger type
88
+ let executionContext;
89
+ if (trigger === 'provision') {
90
+ // Provision context - no installation, no workplace
91
+ executionContext = {
92
+ trigger: 'provision',
93
+ app,
94
+ env: process.env,
95
+ mode: estimateMode ? 'estimate' : 'execute',
96
+ };
97
+ }
98
+ else {
99
+ // Runtime context - has installation, workplace, request
100
+ const workplace = rawContext.workplace;
101
+ const request = rawContext.request;
102
+ const appInstallationId = rawContext.appInstallationId;
103
+ const envVars = process.env;
104
+ const modeValue = estimateMode ? 'estimate' : 'execute';
105
+ if (trigger === 'field_change') {
106
+ const field = rawContext.field;
107
+ executionContext = { trigger: 'field_change', app, appInstallationId, workplace, request, env: envVars, mode: modeValue, field };
108
+ }
109
+ else if (trigger === 'page_action') {
110
+ const page = rawContext.page;
111
+ executionContext = { trigger: 'page_action', app, appInstallationId, workplace, request, env: envVars, mode: modeValue, page };
112
+ }
113
+ else if (trigger === 'form_submit') {
114
+ const form = rawContext.form;
115
+ executionContext = { trigger: 'form_submit', app, appInstallationId, workplace, request, env: envVars, mode: modeValue, form };
116
+ }
117
+ else if (trigger === 'workflow') {
118
+ executionContext = { trigger: 'workflow', app, appInstallationId, workplace, request, env: envVars, mode: modeValue };
119
+ }
120
+ else if (trigger === 'page_context') {
121
+ // Page context trigger - similar to agent but for page context resolution
122
+ executionContext = { trigger: 'agent', app, appInstallationId, workplace, request, env: envVars, mode: modeValue };
123
+ }
124
+ else {
125
+ // Default to agent
126
+ executionContext = { trigger: 'agent', app, appInstallationId, workplace, request, env: envVars, mode: modeValue };
127
+ }
128
+ }
129
+ // Build request-scoped config from env passed in MCP call
130
+ const requestConfig = {
131
+ baseUrl: requestEnv.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? '',
132
+ apiToken: requestEnv.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? '',
133
+ };
134
+ // Call handler with two arguments: (input, context)
135
+ // Wrap in runWithConfig for request-scoped SDK configuration
136
+ const functionResult = await (0, client_1.runWithConfig)(requestConfig, async () => {
137
+ return await fn(inputs, executionContext);
138
+ });
139
+ const billing = (0, utils_1.normalizeBilling)(functionResult.billing);
140
+ return {
141
+ output: functionResult.output,
142
+ billing,
143
+ meta: functionResult.meta ?? {
144
+ success: true,
145
+ message: 'OK',
146
+ toolName,
147
+ },
148
+ effect: functionResult.effect,
149
+ };
150
+ }
151
+ catch (error) {
152
+ // Check if it's an AppAuthInvalidError
153
+ if (error instanceof errors_1.AppAuthInvalidError) {
154
+ return {
155
+ output: null,
156
+ billing: { credits: 0 },
157
+ meta: {
158
+ success: false,
159
+ message: error.message,
160
+ toolName,
161
+ },
162
+ error: {
163
+ code: error.code,
164
+ message: error.message,
165
+ },
166
+ // Note: redirect URL will be added by workflow after detecting APP_AUTH_INVALID
167
+ };
168
+ }
169
+ // Generic error handling for other errors
170
+ const errorMessage = error instanceof Error ? error.message : String(error ?? '');
171
+ return {
172
+ output: null,
173
+ billing: { credits: 0 },
174
+ meta: {
175
+ success: false,
176
+ message: errorMessage,
177
+ toolName,
178
+ },
179
+ error: {
180
+ code: 'TOOL_EXECUTION_ERROR',
181
+ message: errorMessage,
182
+ },
183
+ };
184
+ }
185
+ finally {
186
+ process.env = originalEnv;
187
+ }
188
+ };
189
+ }
@@ -0,0 +1,22 @@
1
+ import type { HealthStatus } from '../types';
2
+ /**
3
+ * Arguments passed to tool call handlers
4
+ */
5
+ export type ToolCallArgs = {
6
+ env?: Record<string, string | undefined>;
7
+ inputs?: Record<string, unknown>;
8
+ context?: Record<string, unknown>;
9
+ estimate?: boolean;
10
+ };
11
+ /**
12
+ * Interface for tracking request state and health status
13
+ */
14
+ export interface RequestState {
15
+ incrementRequestCount(): void;
16
+ shouldShutdown(): boolean;
17
+ getHealthStatus(): HealthStatus;
18
+ }
19
+ /**
20
+ * Supported core API methods
21
+ */
22
+ export type CoreMethod = 'createCommunicationChannel' | 'updateCommunicationChannel' | 'deleteCommunicationChannel' | 'getCommunicationChannel' | 'getCommunicationChannels' | 'communicationChannel.list' | 'communicationChannel.get' | 'workplace.list' | 'workplace.get' | 'sendMessage';
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Parses a JSON string into a Record, returning empty object on failure
3
+ */
4
+ export declare function parseJsonRecord(value?: string): Record<string, string>;
5
+ /**
6
+ * Parses a string environment variable as a number
7
+ */
8
+ export declare function parseNumberEnv(value?: string): number | null;
9
+ /**
10
+ * Merges baked-in environment variables with runtime environment variables
11
+ */
12
+ export declare function mergeRuntimeEnv(): void;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseJsonRecord = parseJsonRecord;
4
+ exports.parseNumberEnv = parseNumberEnv;
5
+ exports.mergeRuntimeEnv = mergeRuntimeEnv;
6
+ /**
7
+ * Parses a JSON string into a Record, returning empty object on failure
8
+ */
9
+ function parseJsonRecord(value) {
10
+ if (!value) {
11
+ return {};
12
+ }
13
+ try {
14
+ return JSON.parse(value);
15
+ }
16
+ catch {
17
+ return {};
18
+ }
19
+ }
20
+ /**
21
+ * Parses a string environment variable as a number
22
+ */
23
+ function parseNumberEnv(value) {
24
+ if (!value) {
25
+ return null;
26
+ }
27
+ const parsed = Number.parseInt(value, 10);
28
+ return Number.isNaN(parsed) ? null : parsed;
29
+ }
30
+ /**
31
+ * Merges baked-in environment variables with runtime environment variables
32
+ */
33
+ function mergeRuntimeEnv() {
34
+ const bakedEnv = parseJsonRecord(process.env.MCP_ENV_JSON);
35
+ const runtimeEnv = parseJsonRecord(process.env.MCP_ENV);
36
+ const merged = { ...bakedEnv, ...runtimeEnv };
37
+ Object.assign(process.env, merged);
38
+ }
@@ -0,0 +1,30 @@
1
+ import http, { IncomingMessage } from 'http';
2
+ import type { APIGatewayProxyResult, CorsOptions, SkedyulServerConfig } from '../../types';
3
+ /**
4
+ * Reads the raw request body from an IncomingMessage
5
+ */
6
+ export declare function readRawRequestBody(req: IncomingMessage): Promise<string>;
7
+ /**
8
+ * Parses JSON body from an IncomingMessage
9
+ */
10
+ export declare function parseJSONBody(req: IncomingMessage): Promise<unknown>;
11
+ /**
12
+ * Sends a JSON response
13
+ */
14
+ export declare function sendJSON(res: http.ServerResponse, statusCode: number, data: unknown): void;
15
+ /**
16
+ * Sends an HTML response
17
+ */
18
+ export declare function sendHTML(res: http.ServerResponse, statusCode: number, html: string): void;
19
+ /**
20
+ * Gets default CORS headers
21
+ */
22
+ export declare function getDefaultHeaders(options?: CorsOptions): Record<string, string>;
23
+ /**
24
+ * Creates an API Gateway proxy response
25
+ */
26
+ export declare function createResponse(statusCode: number, body: unknown, headers: Record<string, string>): APIGatewayProxyResult;
27
+ /**
28
+ * Gets the port to listen on from config or environment
29
+ */
30
+ export declare function getListeningPort(config: SkedyulServerConfig): number;
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readRawRequestBody = readRawRequestBody;
4
+ exports.parseJSONBody = parseJSONBody;
5
+ exports.sendJSON = sendJSON;
6
+ exports.sendHTML = sendHTML;
7
+ exports.getDefaultHeaders = getDefaultHeaders;
8
+ exports.createResponse = createResponse;
9
+ exports.getListeningPort = getListeningPort;
10
+ /**
11
+ * Reads the raw request body from an IncomingMessage
12
+ */
13
+ function readRawRequestBody(req) {
14
+ return new Promise((resolve, reject) => {
15
+ let body = '';
16
+ req.on('data', (chunk) => {
17
+ body += chunk.toString();
18
+ });
19
+ req.on('end', () => {
20
+ resolve(body);
21
+ });
22
+ req.on('error', reject);
23
+ });
24
+ }
25
+ /**
26
+ * Parses JSON body from an IncomingMessage
27
+ */
28
+ async function parseJSONBody(req) {
29
+ const rawBody = await readRawRequestBody(req);
30
+ try {
31
+ return rawBody ? JSON.parse(rawBody) : {};
32
+ }
33
+ catch (err) {
34
+ throw err;
35
+ }
36
+ }
37
+ /**
38
+ * Sends a JSON response
39
+ */
40
+ function sendJSON(res, statusCode, data) {
41
+ res.writeHead(statusCode, { 'Content-Type': 'application/json' });
42
+ res.end(JSON.stringify(data));
43
+ }
44
+ /**
45
+ * Sends an HTML response
46
+ */
47
+ function sendHTML(res, statusCode, html) {
48
+ res.writeHead(statusCode, { 'Content-Type': 'text/html; charset=utf-8' });
49
+ res.end(html);
50
+ }
51
+ /**
52
+ * Gets default CORS headers
53
+ */
54
+ function getDefaultHeaders(options) {
55
+ return {
56
+ 'Content-Type': 'application/json',
57
+ 'Access-Control-Allow-Origin': options?.allowOrigin ?? '*',
58
+ 'Access-Control-Allow-Methods': options?.allowMethods ?? 'GET, POST, OPTIONS',
59
+ 'Access-Control-Allow-Headers': options?.allowHeaders ?? 'Content-Type',
60
+ };
61
+ }
62
+ /**
63
+ * Creates an API Gateway proxy response
64
+ */
65
+ function createResponse(statusCode, body, headers) {
66
+ return {
67
+ statusCode,
68
+ headers,
69
+ body: JSON.stringify(body),
70
+ };
71
+ }
72
+ /**
73
+ * Gets the port to listen on from config or environment
74
+ */
75
+ function getListeningPort(config) {
76
+ const envPort = Number.parseInt(process.env.PORT ?? '', 10);
77
+ if (!Number.isNaN(envPort)) {
78
+ return envPort;
79
+ }
80
+ return config.defaultPort ?? 3000;
81
+ }
@@ -0,0 +1,3 @@
1
+ export { normalizeBilling, toJsonSchema, isToolSchemaWithJson, getZodSchema, getJsonSchemaFromToolSchema, } from './schema';
2
+ export { parseJsonRecord, parseNumberEnv, mergeRuntimeEnv, } from './env';
3
+ export { readRawRequestBody, parseJSONBody, sendJSON, sendHTML, getDefaultHeaders, createResponse, getListeningPort, } from './http';
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getListeningPort = exports.createResponse = exports.getDefaultHeaders = exports.sendHTML = exports.sendJSON = exports.parseJSONBody = exports.readRawRequestBody = exports.mergeRuntimeEnv = exports.parseNumberEnv = exports.parseJsonRecord = exports.getJsonSchemaFromToolSchema = exports.getZodSchema = exports.isToolSchemaWithJson = exports.toJsonSchema = exports.normalizeBilling = void 0;
4
+ // Schema utilities
5
+ var schema_1 = require("./schema");
6
+ Object.defineProperty(exports, "normalizeBilling", { enumerable: true, get: function () { return schema_1.normalizeBilling; } });
7
+ Object.defineProperty(exports, "toJsonSchema", { enumerable: true, get: function () { return schema_1.toJsonSchema; } });
8
+ Object.defineProperty(exports, "isToolSchemaWithJson", { enumerable: true, get: function () { return schema_1.isToolSchemaWithJson; } });
9
+ Object.defineProperty(exports, "getZodSchema", { enumerable: true, get: function () { return schema_1.getZodSchema; } });
10
+ Object.defineProperty(exports, "getJsonSchemaFromToolSchema", { enumerable: true, get: function () { return schema_1.getJsonSchemaFromToolSchema; } });
11
+ // Environment utilities
12
+ var env_1 = require("./env");
13
+ Object.defineProperty(exports, "parseJsonRecord", { enumerable: true, get: function () { return env_1.parseJsonRecord; } });
14
+ Object.defineProperty(exports, "parseNumberEnv", { enumerable: true, get: function () { return env_1.parseNumberEnv; } });
15
+ Object.defineProperty(exports, "mergeRuntimeEnv", { enumerable: true, get: function () { return env_1.mergeRuntimeEnv; } });
16
+ // HTTP utilities
17
+ var http_1 = require("./http");
18
+ Object.defineProperty(exports, "readRawRequestBody", { enumerable: true, get: function () { return http_1.readRawRequestBody; } });
19
+ Object.defineProperty(exports, "parseJSONBody", { enumerable: true, get: function () { return http_1.parseJSONBody; } });
20
+ Object.defineProperty(exports, "sendJSON", { enumerable: true, get: function () { return http_1.sendJSON; } });
21
+ Object.defineProperty(exports, "sendHTML", { enumerable: true, get: function () { return http_1.sendHTML; } });
22
+ Object.defineProperty(exports, "getDefaultHeaders", { enumerable: true, get: function () { return http_1.getDefaultHeaders; } });
23
+ Object.defineProperty(exports, "createResponse", { enumerable: true, get: function () { return http_1.createResponse; } });
24
+ Object.defineProperty(exports, "getListeningPort", { enumerable: true, get: function () { return http_1.getListeningPort; } });
@@ -0,0 +1,22 @@
1
+ import * as z from 'zod';
2
+ import type { BillingInfo, ToolSchema, ToolSchemaWithJson } from '../../types';
3
+ /**
4
+ * Normalizes billing info to ensure credits field exists
5
+ */
6
+ export declare function normalizeBilling(billing?: BillingInfo): BillingInfo;
7
+ /**
8
+ * Converts a Zod schema to JSON Schema format
9
+ */
10
+ export declare function toJsonSchema(schema?: z.ZodTypeAny): Record<string, unknown> | undefined;
11
+ /**
12
+ * Type guard to check if a schema is a ToolSchemaWithJson
13
+ */
14
+ export declare function isToolSchemaWithJson(schema: ToolSchema | undefined): schema is ToolSchemaWithJson;
15
+ /**
16
+ * Extracts the Zod schema from a ToolSchema
17
+ */
18
+ export declare function getZodSchema(schema?: ToolSchema): z.ZodTypeAny | undefined;
19
+ /**
20
+ * Gets JSON schema from a ToolSchema, either from explicit jsonSchema or by converting Zod
21
+ */
22
+ export declare function getJsonSchemaFromToolSchema(schema?: ToolSchema): Record<string, unknown> | undefined;
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.normalizeBilling = normalizeBilling;
37
+ exports.toJsonSchema = toJsonSchema;
38
+ exports.isToolSchemaWithJson = isToolSchemaWithJson;
39
+ exports.getZodSchema = getZodSchema;
40
+ exports.getJsonSchemaFromToolSchema = getJsonSchemaFromToolSchema;
41
+ const z = __importStar(require("zod"));
42
+ /**
43
+ * Normalizes billing info to ensure credits field exists
44
+ */
45
+ function normalizeBilling(billing) {
46
+ if (!billing || typeof billing.credits !== 'number') {
47
+ return { credits: 0 };
48
+ }
49
+ return billing;
50
+ }
51
+ /**
52
+ * Converts a Zod schema to JSON Schema format
53
+ */
54
+ function toJsonSchema(schema) {
55
+ if (!schema)
56
+ return undefined;
57
+ try {
58
+ // Zod v4 has native JSON Schema support via z.toJSONSchema()
59
+ return z.toJSONSchema(schema, {
60
+ unrepresentable: 'any', // Handle z.date(), z.bigint() etc gracefully
61
+ });
62
+ }
63
+ catch (err) {
64
+ console.error('[toJsonSchema] Failed to convert schema:', err);
65
+ return undefined;
66
+ }
67
+ }
68
+ /**
69
+ * Type guard to check if a schema is a ToolSchemaWithJson
70
+ */
71
+ function isToolSchemaWithJson(schema) {
72
+ return Boolean(schema &&
73
+ typeof schema === 'object' &&
74
+ 'zod' in schema &&
75
+ schema.zod instanceof z.ZodType);
76
+ }
77
+ /**
78
+ * Extracts the Zod schema from a ToolSchema
79
+ */
80
+ function getZodSchema(schema) {
81
+ if (!schema)
82
+ return undefined;
83
+ if (schema instanceof z.ZodType) {
84
+ return schema;
85
+ }
86
+ if (isToolSchemaWithJson(schema)) {
87
+ return schema.zod;
88
+ }
89
+ return undefined;
90
+ }
91
+ /**
92
+ * Gets JSON schema from a ToolSchema, either from explicit jsonSchema or by converting Zod
93
+ */
94
+ function getJsonSchemaFromToolSchema(schema) {
95
+ if (!schema)
96
+ return undefined;
97
+ if (isToolSchemaWithJson(schema) && schema.jsonSchema) {
98
+ return schema.jsonSchema;
99
+ }
100
+ const zodSchema = getZodSchema(schema);
101
+ return toJsonSchema(zodSchema);
102
+ }