skedyul 0.1.22 → 0.1.24

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.
@@ -33,13 +33,34 @@ export declare const workplace: {
33
33
  list(args?: ListArgs): Promise<Workplace[]>;
34
34
  get(id: string): Promise<Workplace>;
35
35
  };
36
+ export interface CreateMessageAttachment {
37
+ fileId: string;
38
+ name: string;
39
+ mimeType: string;
40
+ size: number;
41
+ }
42
+ export interface CreateMessageType {
43
+ id?: string | null;
44
+ remoteId?: string | null;
45
+ message: string;
46
+ title?: string | null;
47
+ contentRaw?: string | null;
48
+ newChat?: boolean;
49
+ attachments?: CreateMessageAttachment[];
50
+ }
51
+ export interface ReceiveMessageContact {
52
+ id?: string;
53
+ identifierValue?: string;
54
+ }
36
55
  export interface ReceiveMessageInput {
37
56
  /** Communication channel ID */
38
57
  communicationChannelId: string;
39
58
  /** Sender's identifier (e.g., phone number, email) */
40
59
  from: string;
41
- /** Message content */
42
- message: string;
60
+ /** Message payload */
61
+ message: CreateMessageType;
62
+ /** Optional contact metadata to associate the message */
63
+ contact?: ReceiveMessageContact;
43
64
  /** Optional remote/external message ID (e.g., Twilio MessageSid) */
44
65
  remoteId?: string;
45
66
  }
@@ -119,6 +119,7 @@ exports.communicationChannel = {
119
119
  communicationChannelId: input.communicationChannelId,
120
120
  from: input.from,
121
121
  message: input.message,
122
+ contact: input.contact,
122
123
  ...(input.remoteId ? { remoteId: input.remoteId } : {}),
123
124
  }));
124
125
  return payload;
package/dist/server.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { SkedyulServerConfig, SkedyulServerInstance, ToolRegistry } from './types';
2
- export declare function createSkedyulServer(config: SkedyulServerConfig, registry: ToolRegistry): SkedyulServerInstance;
1
+ import type { SkedyulServerConfig, SkedyulServerInstance, ToolRegistry, WebhookRegistry } from './types';
2
+ export declare function createSkedyulServer(config: SkedyulServerConfig, registry: ToolRegistry, webhookRegistry?: WebhookRegistry): SkedyulServerInstance;
3
3
  export declare const server: {
4
4
  create: typeof createSkedyulServer;
5
5
  };
package/dist/server.js CHANGED
@@ -401,7 +401,7 @@ function getListeningPort(config) {
401
401
  }
402
402
  return config.defaultPort ?? 3000;
403
403
  }
404
- function createSkedyulServer(config, registry) {
404
+ function createSkedyulServer(config, registry, webhookRegistry) {
405
405
  mergeRuntimeEnv();
406
406
  if (config.coreApi?.service) {
407
407
  service_1.coreApiService.register(config.coreApi.service);
@@ -476,11 +476,11 @@ function createSkedyulServer(config, registry) {
476
476
  });
477
477
  }
478
478
  if (config.computeLayer === 'dedicated') {
479
- return createDedicatedServerInstance(config, tools, callTool, state, mcpServer);
479
+ return createDedicatedServerInstance(config, tools, callTool, state, mcpServer, webhookRegistry);
480
480
  }
481
- return createServerlessInstance(config, tools, callTool, state, mcpServer, registry);
481
+ return createServerlessInstance(config, tools, callTool, state, mcpServer, registry, webhookRegistry);
482
482
  }
483
- function createDedicatedServerInstance(config, tools, callTool, state, mcpServer) {
483
+ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer, webhookRegistry) {
484
484
  const port = getListeningPort(config);
485
485
  const httpServer = http_1.default.createServer(async (req, res) => {
486
486
  function sendCoreResult(result) {
@@ -493,6 +493,90 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
493
493
  sendJSON(res, 200, state.getHealthStatus());
494
494
  return;
495
495
  }
496
+ // Handle webhook requests: /webhooks/{handle}
497
+ if (pathname.startsWith('/webhooks/') && webhookRegistry) {
498
+ const handle = pathname.slice('/webhooks/'.length);
499
+ const webhookDef = webhookRegistry[handle];
500
+ if (!webhookDef) {
501
+ sendJSON(res, 404, { error: `Webhook handler '${handle}' not found` });
502
+ return;
503
+ }
504
+ // Check if HTTP method is allowed
505
+ const allowedMethods = webhookDef.methods ?? ['POST'];
506
+ if (!allowedMethods.includes(req.method)) {
507
+ sendJSON(res, 405, { error: `Method ${req.method} not allowed` });
508
+ return;
509
+ }
510
+ // Read raw request body
511
+ let rawBody;
512
+ try {
513
+ rawBody = await readRawRequestBody(req);
514
+ }
515
+ catch {
516
+ sendJSON(res, 400, { error: 'Failed to read request body' });
517
+ return;
518
+ }
519
+ // Parse body based on content type
520
+ let parsedBody;
521
+ const contentType = req.headers['content-type'] ?? '';
522
+ if (contentType.includes('application/json')) {
523
+ try {
524
+ parsedBody = rawBody ? JSON.parse(rawBody) : {};
525
+ }
526
+ catch {
527
+ parsedBody = rawBody;
528
+ }
529
+ }
530
+ else {
531
+ parsedBody = rawBody;
532
+ }
533
+ // Build WebhookRequest
534
+ const webhookRequest = {
535
+ method: req.method ?? 'POST',
536
+ url: url.toString(),
537
+ path: pathname,
538
+ headers: req.headers,
539
+ query: Object.fromEntries(url.searchParams.entries()),
540
+ body: parsedBody,
541
+ rawBody: rawBody ? Buffer.from(rawBody, 'utf-8') : undefined,
542
+ };
543
+ // Build WebhookContext
544
+ const webhookContext = {
545
+ env: process.env,
546
+ };
547
+ // Invoke the handler
548
+ let webhookResponse;
549
+ try {
550
+ webhookResponse = await webhookDef.handler(webhookRequest, webhookContext);
551
+ }
552
+ catch (err) {
553
+ console.error(`Webhook handler '${handle}' error:`, err);
554
+ sendJSON(res, 500, { error: 'Webhook handler error' });
555
+ return;
556
+ }
557
+ // Send response
558
+ const status = webhookResponse.status ?? 200;
559
+ const responseHeaders = {
560
+ ...webhookResponse.headers,
561
+ };
562
+ // Default to JSON content type if not specified
563
+ if (!responseHeaders['Content-Type'] && !responseHeaders['content-type']) {
564
+ responseHeaders['Content-Type'] = 'application/json';
565
+ }
566
+ res.writeHead(status, responseHeaders);
567
+ if (webhookResponse.body !== undefined) {
568
+ if (typeof webhookResponse.body === 'string') {
569
+ res.end(webhookResponse.body);
570
+ }
571
+ else {
572
+ res.end(JSON.stringify(webhookResponse.body));
573
+ }
574
+ }
575
+ else {
576
+ res.end();
577
+ }
578
+ return;
579
+ }
496
580
  if (pathname === '/estimate' && req.method === 'POST') {
497
581
  let estimateBody;
498
582
  try {
@@ -657,7 +741,7 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
657
741
  getHealthStatus: () => state.getHealthStatus(),
658
742
  };
659
743
  }
660
- function createServerlessInstance(config, tools, callTool, state, mcpServer, registry) {
744
+ function createServerlessInstance(config, tools, callTool, state, mcpServer, registry, webhookRegistry) {
661
745
  const headers = getDefaultHeaders(config.cors);
662
746
  return {
663
747
  async handler(event) {
@@ -667,6 +751,81 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer, reg
667
751
  if (method === 'OPTIONS') {
668
752
  return createResponse(200, { message: 'OK' }, headers);
669
753
  }
754
+ // Handle webhook requests: /webhooks/{handle}
755
+ if (path.startsWith('/webhooks/') && webhookRegistry) {
756
+ const handle = path.slice('/webhooks/'.length);
757
+ const webhookDef = webhookRegistry[handle];
758
+ if (!webhookDef) {
759
+ return createResponse(404, { error: `Webhook handler '${handle}' not found` }, headers);
760
+ }
761
+ // Check if HTTP method is allowed
762
+ const allowedMethods = webhookDef.methods ?? ['POST'];
763
+ if (!allowedMethods.includes(method)) {
764
+ return createResponse(405, { error: `Method ${method} not allowed` }, headers);
765
+ }
766
+ // Get raw body
767
+ const rawBody = event.body ?? '';
768
+ // Parse body based on content type
769
+ let parsedBody;
770
+ const contentType = event.headers?.['content-type'] ?? event.headers?.['Content-Type'] ?? '';
771
+ if (contentType.includes('application/json')) {
772
+ try {
773
+ parsedBody = rawBody ? JSON.parse(rawBody) : {};
774
+ }
775
+ catch {
776
+ parsedBody = rawBody;
777
+ }
778
+ }
779
+ else {
780
+ parsedBody = rawBody;
781
+ }
782
+ // Build URL
783
+ const forwardedProto = event.headers?.['x-forwarded-proto'] ??
784
+ event.headers?.['X-Forwarded-Proto'];
785
+ const protocol = forwardedProto ?? 'https';
786
+ const host = event.headers?.host ?? event.headers?.Host ?? 'localhost';
787
+ const queryString = event.queryStringParameters
788
+ ? '?' + new URLSearchParams(event.queryStringParameters).toString()
789
+ : '';
790
+ const webhookUrl = `${protocol}://${host}${path}${queryString}`;
791
+ // Build WebhookRequest
792
+ const webhookRequest = {
793
+ method,
794
+ url: webhookUrl,
795
+ path,
796
+ headers: event.headers,
797
+ query: event.queryStringParameters ?? {},
798
+ body: parsedBody,
799
+ rawBody: rawBody ? Buffer.from(rawBody, 'utf-8') : undefined,
800
+ };
801
+ // Build WebhookContext
802
+ const webhookContext = {
803
+ env: process.env,
804
+ };
805
+ // Invoke the handler
806
+ let webhookResponse;
807
+ try {
808
+ webhookResponse = await webhookDef.handler(webhookRequest, webhookContext);
809
+ }
810
+ catch (err) {
811
+ console.error(`Webhook handler '${handle}' error:`, err);
812
+ return createResponse(500, { error: 'Webhook handler error' }, headers);
813
+ }
814
+ // Build response headers
815
+ const responseHeaders = {
816
+ ...headers,
817
+ ...webhookResponse.headers,
818
+ };
819
+ const status = webhookResponse.status ?? 200;
820
+ const body = webhookResponse.body;
821
+ return {
822
+ statusCode: status,
823
+ headers: responseHeaders,
824
+ body: body !== undefined
825
+ ? (typeof body === 'string' ? body : JSON.stringify(body))
826
+ : '',
827
+ };
828
+ }
670
829
  if (path === '/core' && method === 'POST') {
671
830
  let coreBody;
672
831
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skedyul",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
4
4
  "description": "The Skedyul SDK for Node.js",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",