skedyul 1.2.44 → 1.2.48

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 (54) hide show
  1. package/dist/cli/commands/workflows.d.ts +1 -0
  2. package/dist/cli/index.js +3670 -9073
  3. package/dist/cli/utils/auth.d.ts +4 -1
  4. package/dist/cli/utils/auth.js +32 -8
  5. package/dist/cli/utils/config.d.ts +23 -0
  6. package/dist/cli/utils/env-sync.d.ts +46 -0
  7. package/dist/cli/utils/mcp-http-client.d.ts +74 -0
  8. package/dist/cli/utils/migration-approval.d.ts +39 -0
  9. package/dist/cli/utils/mock-context.d.ts +19 -9
  10. package/dist/cli/utils/sse.d.ts +33 -0
  11. package/dist/cli/utils.d.ts +5 -1
  12. package/dist/compiler/types.d.ts +11 -9
  13. package/dist/config/schema-loader.d.ts +15 -2
  14. package/dist/config/types/model.d.ts +2 -0
  15. package/dist/config/types/page.d.ts +9 -0
  16. package/dist/context/index.d.ts +2 -2
  17. package/dist/context/resolver.d.ts +29 -28
  18. package/dist/context/types.d.ts +195 -37
  19. package/dist/core/client.d.ts +189 -233
  20. package/dist/dedicated/server.js +252 -163
  21. package/dist/esm/index.mjs +1149 -7671
  22. package/dist/index.d.ts +11 -6
  23. package/dist/index.js +1194 -7669
  24. package/dist/scheduling/calculateWaitTime.d.ts +16 -0
  25. package/dist/scheduling/index.d.ts +11 -0
  26. package/dist/scheduling/index.js +334 -0
  27. package/dist/scheduling/index.mjs +305 -0
  28. package/dist/scheduling/isTimeInWindow.d.ts +15 -0
  29. package/dist/scheduling/types-workflow.d.ts +54 -0
  30. package/dist/scheduling/types.d.ts +166 -0
  31. package/dist/schemas/agent-schema-v3.d.ts +406 -60
  32. package/dist/schemas/agent-schema-v3.js +248 -75
  33. package/dist/schemas/agent-schema-v3.mjs +234 -73
  34. package/dist/schemas/agent-schema.js +3 -7295
  35. package/dist/schemas/agent-schema.mjs +3 -7323
  36. package/dist/schemas/crm-schema.d.ts +53 -19
  37. package/dist/schemas/index.d.ts +1 -1
  38. package/dist/schemas.d.ts +128 -40
  39. package/dist/server/route-handlers/handlers.d.ts +7 -0
  40. package/dist/server/utils/env.d.ts +9 -0
  41. package/dist/server/utils/index.d.ts +1 -0
  42. package/dist/server/utils/mcp-response.d.ts +11 -0
  43. package/dist/server.js +252 -163
  44. package/dist/serverless/server.mjs +252 -163
  45. package/dist/skills/index.d.ts +1 -1
  46. package/dist/skills/types.d.ts +34 -23
  47. package/dist/skills/types.js +8 -17
  48. package/dist/skills/types.mjs +7 -16
  49. package/dist/types/index.d.ts +3 -3
  50. package/dist/types/server.d.ts +1 -0
  51. package/dist/types/tool-context.d.ts +31 -4
  52. package/dist/types/tool-response.d.ts +2 -0
  53. package/dist/types/tool.d.ts +33 -1
  54. package/package.json +8 -1
@@ -253,6 +253,8 @@ export interface InstanceMeta {
253
253
  */
254
254
  export interface InstanceData {
255
255
  id: string;
256
+ /** The app installation this instance belongs to (if any) */
257
+ appInstallationId?: string | null;
256
258
  _meta: InstanceMeta;
257
259
  [fieldHandle: string]: unknown;
258
260
  }
@@ -272,116 +274,20 @@ export interface InstanceListArgs {
272
274
  /** Filter conditions using StructuredFilter format: { field: { operator: value } } */
273
275
  filter?: StructuredFilter;
274
276
  }
275
- export declare const instance: {
276
- /**
277
- * List instances of an internal model.
278
- *
279
- * The API token determines the context:
280
- * - sk_wkp_ tokens: scoped to the token's app installation
281
- * - sk_app_ tokens: searches across ALL installations for the app
282
- *
283
- * @example
284
- * ```ts
285
- * // List with filters
286
- * const { data, pagination } = await instance.list('compliance_record', {
287
- * filter: { status: 'pending' },
288
- * page: 1,
289
- * limit: 10,
290
- * })
291
- *
292
- * // Cross-installation search (with sk_app_ token)
293
- * const { data } = await instance.list('phone_number', {
294
- * filter: { phone: '+1234567890' },
295
- * })
296
- * ```
297
- */
277
+ /**
278
+ * Interface for instance operations.
279
+ *
280
+ * Used by both the global `instance` export (uses current config) and
281
+ * scoped clients returned by `token.exchange` (bound to specific sk_wkp_ token).
282
+ */
283
+ export interface InstanceClient {
298
284
  list(modelHandle: string, args?: InstanceListArgs): Promise<InstanceListResult>;
299
- /**
300
- * Get a single instance by ID.
301
- *
302
- * The API token determines the context (app installation is embedded in sk_wkp_ tokens).
303
- *
304
- * @example
305
- * ```ts
306
- * const record = await instance.get('phone_number', 'ins_abc123')
307
- * ```
308
- */
309
285
  get(modelHandle: string, id: string): Promise<InstanceData | null>;
310
- /**
311
- * Create a new instance of an internal model.
312
- *
313
- * The API token determines the context (app installation is embedded in sk_wkp_ tokens).
314
- *
315
- * @example
316
- * ```ts
317
- * const newRecord = await instance.create('compliance_record', {
318
- * status: 'pending',
319
- * document_url: 'https://...',
320
- * })
321
- * ```
322
- */
323
286
  create(modelHandle: string, data: Record<string, unknown>): Promise<InstanceData>;
324
- /**
325
- * Update an existing instance.
326
- *
327
- * The API token determines the context (app installation is embedded in sk_wkp_ tokens).
328
- *
329
- * @example
330
- * ```ts
331
- * const updated = await instance.update('compliance_record', 'ins_abc123', {
332
- * status: 'approved',
333
- * bundle_sid: 'BU123456',
334
- * })
335
- * ```
336
- */
337
287
  update(modelHandle: string, id: string, data: Record<string, unknown>): Promise<InstanceData>;
338
- /**
339
- * Delete an existing instance.
340
- *
341
- * The API token determines the context (app installation is embedded in sk_wkp_ tokens).
342
- *
343
- * @example
344
- * ```ts
345
- * const { deleted } = await instance.delete('phone_number', 'ins_abc123')
346
- * ```
347
- */
348
288
  delete(modelHandle: string, id: string): Promise<{
349
289
  deleted: boolean;
350
290
  }>;
351
- /**
352
- * Delete multiple instances of an internal model in a single batch operation.
353
- *
354
- * This is more efficient than calling delete() multiple times as it reduces
355
- * API overhead and executes all deletes in a single transaction.
356
- *
357
- * Supports two modes:
358
- * - **By IDs**: Delete specific instances by their IDs
359
- * - **By Filter**: Delete instances matching a StructuredFilter
360
- *
361
- * The API token determines the context (app installation is embedded in sk_wkp_ tokens).
362
- *
363
- * @param modelHandle - The model handle from provision config
364
- * @param options - Either { ids: string[] } or { filter: StructuredFilter }
365
- * @returns Object containing deleted instance IDs and any errors that occurred
366
- *
367
- * @example
368
- * ```ts
369
- * // Delete by IDs
370
- * const { deleted, errors } = await instance.deleteMany('panel_result', {
371
- * ids: ['ins_abc123', 'ins_def456'],
372
- * })
373
- *
374
- * // Delete by filter
375
- * const { deleted, errors } = await instance.deleteMany('panel_result', {
376
- * filter: { status: { eq: 'pending' } },
377
- * })
378
- *
379
- * if (errors.length > 0) {
380
- * console.log('Some items failed:', errors)
381
- * }
382
- * console.log('Deleted:', deleted.length, 'instances')
383
- * ```
384
- */
385
291
  deleteMany(modelHandle: string, options: {
386
292
  ids: string[];
387
293
  } | {
@@ -393,31 +299,6 @@ export declare const instance: {
393
299
  error: string;
394
300
  }>;
395
301
  }>;
396
- /**
397
- * Create multiple instances of an internal model in a single batch operation.
398
- *
399
- * This is more efficient than calling create() multiple times as it reduces
400
- * API overhead and executes all creates in a single transaction.
401
- *
402
- * The API token determines the context (app installation is embedded in sk_wkp_ tokens).
403
- *
404
- * @param modelHandle - The model handle from provision config
405
- * @param items - Array of data objects to create as instances
406
- * @returns Object containing created instances and any errors that occurred
407
- *
408
- * @example
409
- * ```ts
410
- * const { created, errors } = await instance.createMany('panel_result', [
411
- * { test_name: 'Glucose', value_string: '5.2', unit: 'mmol/L' },
412
- * { test_name: 'Creatinine', value_string: '80', unit: 'umol/L' },
413
- * ])
414
- *
415
- * if (errors.length > 0) {
416
- * console.log('Some items failed:', errors)
417
- * }
418
- * console.log('Created:', created.length, 'instances')
419
- * ```
420
- */
421
302
  createMany(modelHandle: string, items: Record<string, unknown>[]): Promise<{
422
303
  created: InstanceData[];
423
304
  errors: Array<{
@@ -425,31 +306,6 @@ export declare const instance: {
425
306
  error: string;
426
307
  }>;
427
308
  }>;
428
- /**
429
- * Update multiple instances of an internal model in a single batch operation.
430
- *
431
- * This is more efficient than calling update() multiple times as it reduces
432
- * API overhead and executes all updates in a single transaction.
433
- *
434
- * The API token determines the context (app installation is embedded in sk_wkp_ tokens).
435
- *
436
- * @param modelHandle - The model handle from provision config
437
- * @param items - Array of objects containing id and data to update
438
- * @returns Object containing updated instances and any errors that occurred
439
- *
440
- * @example
441
- * ```ts
442
- * const { updated, errors } = await instance.updateMany('panel_result', [
443
- * { id: 'ins_abc123', data: { value_string: '5.5' } },
444
- * { id: 'ins_def456', data: { value_string: '85' } },
445
- * ])
446
- *
447
- * if (errors.length > 0) {
448
- * console.log('Some items failed:', errors)
449
- * }
450
- * console.log('Updated:', updated.length, 'instances')
451
- * ```
452
- */
453
309
  updateMany(modelHandle: string, items: Array<{
454
310
  id: string;
455
311
  data: Record<string, unknown>;
@@ -460,118 +316,91 @@ export declare const instance: {
460
316
  error: string;
461
317
  }>;
462
318
  }>;
463
- /**
464
- * Upsert multiple instances of an internal model in a single batch operation.
465
- *
466
- * Creates instances if they don't exist, updates them if they do (based on matchField).
467
- * This is more efficient than calling upsert() multiple times as it reduces
468
- * API overhead and executes all upserts in a single transaction.
469
- *
470
- * The API token determines the context (app installation is embedded in sk_wkp_ tokens).
471
- *
472
- * @param modelHandle - The model handle from provision config
473
- * @param items - Array of data objects to upsert as instances
474
- * @param matchField - The field handle to match existing instances (e.g., 'vetnostics_id')
475
- * @returns Object containing upserted instances with mode and any errors that occurred
476
- *
477
- * @example
478
- * ```ts
479
- * const { results, errors } = await instance.upsertMany('panel_result', [
480
- * { vetnostics_id: '25-54966975/622/glucose', test_name: 'Glucose', value_string: '5.2' },
481
- * { vetnostics_id: '25-54966975/622/creatinine', test_name: 'Creatinine', value_string: '80' },
482
- * ], 'vetnostics_id')
483
- *
484
- * if (errors.length > 0) {
485
- * console.log('Some items failed:', errors)
486
- * }
487
- * const created = results.filter(r => r.mode === 'created')
488
- * const updated = results.filter(r => r.mode === 'updated')
489
- * console.log('Created:', created.length, 'Updated:', updated.length)
490
- * ```
491
- */
492
319
  upsertMany(modelHandle: string, items: Record<string, unknown>[], matchField: string): Promise<{
493
320
  results: Array<InstanceData & {
494
- mode: "created" | "updated";
321
+ mode: 'created' | 'updated';
495
322
  }>;
496
323
  errors: Array<{
497
324
  index: number;
498
325
  error: string;
499
326
  }>;
500
327
  }>;
328
+ isConfigured(modelHandle: string): Promise<boolean>;
329
+ getConfiguredModels(modelHandles: string[]): Promise<Map<string, boolean>>;
330
+ }
331
+ /**
332
+ * Create an instance client with a specific configuration.
333
+ *
334
+ * This is useful for creating clients bound to specific tokens (e.g., from token.exchange).
335
+ * All methods on the returned client use the provided configuration.
336
+ *
337
+ * @param config - Client configuration with baseUrl and apiToken
338
+ * @returns InstanceClient bound to the provided config
339
+ *
340
+ * @example
341
+ * ```ts
342
+ * // After getting a scoped token via token.exchange
343
+ * const scopedClient = createInstanceClient({
344
+ * baseUrl: getConfig().baseUrl,
345
+ * apiToken: scopedToken,
346
+ * })
347
+ * await scopedClient.create('studio', { ... })
348
+ * ```
349
+ */
350
+ export declare function createInstanceClient(config: ClientConfig): InstanceClient;
351
+ export declare const instance: InstanceClient;
352
+ export declare const token: {
501
353
  /**
502
- * Check if a model is configured (linked) for the current app installation.
354
+ * Exchange an sk_app_ or sk_prv_ token for an installation-scoped InstanceClient.
503
355
  *
504
- * This is useful for best-effort sync scenarios where you want to check
505
- * which models are available before attempting to create instances.
356
+ * **Requires sk_app_ or sk_prv_ token** - works with app-level or provision tokens.
357
+ * Used by developer tools after discovering `appInstallationId` from a record.
506
358
  *
507
- * The API token determines the context (app installation is embedded in sk_wkp_ tokens).
359
+ * Returns an InstanceClient bound to the installation's sk_wkp_ token.
360
+ * All CRM writes should use this scoped client.
508
361
  *
509
- * @param modelHandle - The model handle from provision config
510
- * @returns true if the model is configured and has a valid targetId, false otherwise
362
+ * The underlying JWT is short-lived (1 hour) and scoped to the specific installation.
511
363
  *
512
364
  * @example
513
365
  * ```ts
514
- * // Check if models are configured before syncing
515
- * const isTestOrderConfigured = await instance.isConfigured('test_order')
516
- * const isTestReportConfigured = await instance.isConfigured('test_report')
517
- *
518
- * if (isTestOrderConfigured) {
519
- * await instance.create('test_order', orderData)
366
+ * // Developer tool: discover exchange write
367
+ * const accessRequest = await instance.get('access_request', id) // uses sk_prv_
368
+ * if (!accessRequest?.appInstallationId) {
369
+ * throw new Error('Access request missing appInstallationId')
520
370
  * }
521
- * ```
522
- */
523
- isConfigured(modelHandle: string): Promise<boolean>;
524
- /**
525
- * Check which models from a list are configured for the current app installation.
526
- *
527
- * This is more efficient than calling isConfigured() multiple times as it
528
- * makes a single API call to check all models at once.
529
- *
530
- * The API token determines the context (app installation is embedded in sk_wkp_ tokens).
531
371
  *
532
- * @param modelHandles - Array of model handles from provision config
533
- * @returns Map of model handle to configuration status
372
+ * // Exchange for a scoped instance client
373
+ * const scopedInstance = await token.exchange(accessRequest.appInstallationId)
534
374
  *
535
- * @example
536
- * ```ts
537
- * // Check multiple models at once
538
- * const configStatus = await instance.getConfiguredModels([
539
- * 'test_order',
540
- * 'test_report',
541
- * 'panel_result',
542
- * 'culture_result',
543
- * ])
544
- *
545
- * if (configStatus.get('test_order')) {
546
- * // test_order is configured
547
- * }
375
+ * // All writes use the scoped client (sk_wkp_ internally)
376
+ * await scopedInstance.create('studio', { ... })
377
+ * await scopedInstance.update('access_request', id, { status: 'APPROVED' })
548
378
  * ```
549
379
  */
550
- getConfiguredModels(modelHandles: string[]): Promise<Map<string, boolean>>;
551
- };
552
- export declare const token: {
380
+ exchange(appInstallationId: string): Promise<InstanceClient>;
553
381
  /**
554
- * Exchange an sk_app_ token for an installation-scoped sk_wkp_ JWT.
382
+ * Exchange an sk_app_ or sk_prv_ token for a raw installation-scoped JWT.
555
383
  *
556
- * **Requires sk_app_ token** - only works with app-level tokens.
557
- * Used after identifying the target installation (e.g., via instance.search).
384
+ * **Requires sk_app_ or sk_prv_ token** - works with app-level or provision tokens.
385
+ * For most use cases, prefer `token.exchange()` which returns a ready-to-use InstanceClient.
558
386
  *
559
- * The returned JWT is short-lived (1 hour) and scoped to the specific installation.
387
+ * Use this when you need the raw token string (e.g., for passing to external services,
388
+ * storing for later use, or advanced scenarios requiring manual config management).
560
389
  *
561
390
  * @example
562
391
  * ```ts
563
- * // After finding the installation via instance.search
564
- * const { token: scopedToken } = await token.exchange(appInstallationId)
392
+ * // Get raw token for advanced use cases
393
+ * const { token: scopedToken, appInstallationId } = await token.exchangeRaw(installId)
565
394
  *
566
- * // Use the scoped token for subsequent operations
395
+ * // Manual config management
567
396
  * runWithConfig({ apiToken: scopedToken, baseUrl: config.baseUrl }, async () => {
568
- * const channels = await communicationChannel.list({ filter: { identifierValue: phoneNumber } })
569
- * // ...
397
+ * await communicationChannel.list({ filter: { ... } })
570
398
  * })
571
399
  * ```
572
400
  */
573
- exchange(appInstallationId: string): Promise<{
401
+ exchangeRaw(appInstallationId: string): Promise<{
574
402
  token: string;
403
+ appInstallationId: string;
575
404
  }>;
576
405
  };
577
406
  /**
@@ -809,6 +638,133 @@ export declare const webhook: {
809
638
  webhooks: WebhookListItem[];
810
639
  }>;
811
640
  };
641
+ /**
642
+ * Parameters for cron.subscribe
643
+ */
644
+ export interface CronSubscribeParams {
645
+ /** Name of the tool to invoke */
646
+ toolName: string;
647
+ /** Cron schedule expression (e.g., "0/20 9-17 * * 1-5") */
648
+ schedule: string;
649
+ /** Timezone for the schedule (e.g., "America/New_York"). Defaults to UTC. */
650
+ timezone?: string;
651
+ /** Inputs to pass to the tool on each invocation */
652
+ inputs?: Record<string, unknown>;
653
+ /** Key for cursor sharing (defaults to toolName if not specified) */
654
+ cursorKey?: string;
655
+ /** Optional human-friendly label */
656
+ label?: string;
657
+ }
658
+ /**
659
+ * Response from cron.subscribe
660
+ */
661
+ export interface CronSubscribeResult {
662
+ /** Subscription ID */
663
+ id: string;
664
+ /** Name of the tool to invoke */
665
+ toolName: string;
666
+ /** Schedule expression */
667
+ schedule: string;
668
+ /** Timezone for the schedule */
669
+ timezone: string;
670
+ }
671
+ /**
672
+ * Cron subscription info returned from cron.list
673
+ */
674
+ export interface CronSubscriptionItem {
675
+ /** Subscription ID */
676
+ id: string;
677
+ /** Name of the tool to invoke */
678
+ toolName: string;
679
+ /** Schedule expression */
680
+ schedule: string;
681
+ /** Timezone for the schedule */
682
+ timezone: string;
683
+ /** Whether this subscription is enabled */
684
+ enabled: boolean;
685
+ /** Inputs passed to the tool */
686
+ inputs: Record<string, unknown> | null;
687
+ /** Key for cursor sharing */
688
+ cursorKey: string | null;
689
+ /** Human-friendly label */
690
+ label: string | null;
691
+ /** ISO timestamp when created */
692
+ createdAt: string;
693
+ }
694
+ /**
695
+ * Options for cron.list
696
+ */
697
+ export interface CronListOptions {
698
+ /** Filter by tool name */
699
+ toolName?: string;
700
+ }
701
+ export declare const cron: {
702
+ /**
703
+ * Subscribe to run a tool on a schedule.
704
+ *
705
+ * Creates a cron subscription that will invoke the specified tool
706
+ * at the given schedule. Multiple subscriptions can share cursor
707
+ * state via the cursorKey parameter.
708
+ *
709
+ * **Requires sk_wkp_ token** - subscriptions are scoped to the app installation.
710
+ *
711
+ * @example
712
+ * ```ts
713
+ * // Work hours: sync every 20 mins
714
+ * await cron.subscribe({
715
+ * toolName: 'sync_lab_results',
716
+ * schedule: '0,20,40 9-17 * * 1-5', // 9am-5pm Mon-Fri
717
+ * timezone: 'America/New_York',
718
+ * inputs: { source: 'vetnostics' },
719
+ * label: 'Work hours sync',
720
+ * })
721
+ *
722
+ * // After hours: sync every 3 hours (shares cursor with work hours)
723
+ * await cron.subscribe({
724
+ * toolName: 'sync_lab_results',
725
+ * schedule: '0 0,3,6,9,12,15,18,21 * * *',
726
+ * timezone: 'America/New_York',
727
+ * inputs: { source: 'vetnostics' },
728
+ * label: 'After hours sync',
729
+ * })
730
+ * ```
731
+ */
732
+ subscribe(params: CronSubscribeParams): Promise<CronSubscribeResult>;
733
+ /**
734
+ * Unsubscribe from a cron subscription.
735
+ *
736
+ * Stops the scheduled tool invocation and deletes the subscription.
737
+ *
738
+ * @param subscriptionId - The subscription ID to delete
739
+ * @returns Whether the subscription was deleted (false if not found)
740
+ *
741
+ * @example
742
+ * ```ts
743
+ * const { deleted } = await cron.unsubscribe('crsub_abc123')
744
+ * ```
745
+ */
746
+ unsubscribe(subscriptionId: string): Promise<{
747
+ deleted: boolean;
748
+ }>;
749
+ /**
750
+ * List cron subscriptions for this installation.
751
+ *
752
+ * @param options - Optional filter by tool name
753
+ * @returns Array of cron subscriptions
754
+ *
755
+ * @example
756
+ * ```ts
757
+ * // List all subscriptions
758
+ * const { subscriptions } = await cron.list()
759
+ *
760
+ * // List subscriptions for a specific tool
761
+ * const { subscriptions } = await cron.list({ toolName: 'sync_lab_results' })
762
+ * ```
763
+ */
764
+ list(options?: CronListOptions): Promise<{
765
+ subscriptions: CronSubscriptionItem[];
766
+ }>;
767
+ };
812
768
  /**
813
769
  * Parameters for resource.link
814
770
  */