@kadoa/mcp 0.4.2 → 0.4.3-rc.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 (2) hide show
  1. package/dist/index.js +716 -615
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -43925,6 +43925,90 @@ var init_dist_node = __esm(() => {
43925
43925
  // node_modules/@kadoa/node-sdk/dist/index.mjs
43926
43926
  import { URL as URL$1, URLSearchParams } from "url";
43927
43927
  import assert2 from "assert";
43928
+ function mapChange(raw) {
43929
+ return {
43930
+ id: raw.id,
43931
+ workflowId: raw.workflowId,
43932
+ data: raw.data,
43933
+ differences: coalesceDifferences(raw.differences),
43934
+ url: raw.url,
43935
+ summary: raw.summary,
43936
+ screenshotUrl: raw.screenshotUrl,
43937
+ createdAt: raw.createdAt
43938
+ };
43939
+ }
43940
+ function coalesceDifferences(raw) {
43941
+ if (!raw)
43942
+ return;
43943
+ const addedByRow = /* @__PURE__ */ new Map;
43944
+ const removedByRow = /* @__PURE__ */ new Map;
43945
+ const passthrough = [];
43946
+ for (const diff of raw) {
43947
+ if (diff.type === "added" && diff.rowRef?.currentRowId) {
43948
+ addedByRow.set(diff.rowRef.currentRowId, diff);
43949
+ } else if (diff.type === "removed" && diff.rowRef?.previousRowId) {
43950
+ removedByRow.set(diff.rowRef.previousRowId, diff);
43951
+ } else {
43952
+ passthrough.push(diff);
43953
+ }
43954
+ }
43955
+ const result = [];
43956
+ for (const [rowId, added] of addedByRow) {
43957
+ const removed = removedByRow.get(rowId);
43958
+ if (removed) {
43959
+ removedByRow.delete(rowId);
43960
+ result.push(mergeAddedRemoved(added, removed));
43961
+ } else {
43962
+ result.push(mapDifference(added));
43963
+ }
43964
+ }
43965
+ for (const removed of removedByRow.values()) {
43966
+ result.push(mapDifference(removed));
43967
+ }
43968
+ for (const diff of passthrough) {
43969
+ result.push(mapDifference(diff));
43970
+ }
43971
+ return result;
43972
+ }
43973
+ function mergeAddedRemoved(added, removed) {
43974
+ const previousByKey = /* @__PURE__ */ new Map;
43975
+ for (const f of removed.fields ?? []) {
43976
+ if (f.key !== undefined)
43977
+ previousByKey.set(f.key, f.value);
43978
+ }
43979
+ const fields = (added.fields ?? []).map((f) => ({
43980
+ key: f.key,
43981
+ value: f.value,
43982
+ previousValue: f.key !== undefined ? previousByKey.get(f.key) : undefined
43983
+ }));
43984
+ const addedKeys = new Set((added.fields ?? []).map((f) => f.key));
43985
+ for (const f of removed.fields ?? []) {
43986
+ if (!addedKeys.has(f.key)) {
43987
+ fields.push({ key: f.key, value: undefined, previousValue: f.value });
43988
+ }
43989
+ }
43990
+ return { type: ChangeDifferenceType.Changed, fields };
43991
+ }
43992
+ function mapDifference(raw) {
43993
+ return {
43994
+ type: raw.type,
43995
+ fields: raw.fields?.map(mapField)
43996
+ };
43997
+ }
43998
+ function mapField(raw) {
43999
+ return {
44000
+ key: raw.key,
44001
+ value: raw.value,
44002
+ previousValue: raw.previousValue
44003
+ };
44004
+ }
44005
+ function mapListChangesResponse(raw) {
44006
+ return {
44007
+ changes: (raw.changes ?? []).map(mapChange),
44008
+ pagination: raw.pagination,
44009
+ changesCount: raw.changesCount ?? 0
44010
+ };
44011
+ }
43928
44012
  function setFlattenedQueryParams(urlSearchParams, parameter, key = "") {
43929
44013
  if (parameter == null)
43930
44014
  return;
@@ -43948,6 +44032,40 @@ function createCrawlerDomain(client) {
43948
44032
  session: new CrawlerSessionService(client)
43949
44033
  };
43950
44034
  }
44035
+ function getFieldName(field) {
44036
+ return "name" in field && typeof field.name === "string" ? field.name : undefined;
44037
+ }
44038
+ function buildAgenticPrompt(params) {
44039
+ if (params.userPrompt) {
44040
+ return params.userPrompt;
44041
+ }
44042
+ const fieldNames = params.fields.map((field) => getFieldName(field)).filter((name) => Boolean(name));
44043
+ if (fieldNames.length === 0) {
44044
+ return DEFAULT_AGENTIC_PROMPT;
44045
+ }
44046
+ const fieldList = fieldNames.join(", ");
44047
+ if (params.entity) {
44048
+ return `extract all ${params.entity} entities from this page and return these fields: ${fieldList}`;
44049
+ }
44050
+ return `extract all records from this page and return these fields: ${fieldList}`;
44051
+ }
44052
+ function getFieldName2(field) {
44053
+ return "name" in field && typeof field.name === "string" ? field.name : undefined;
44054
+ }
44055
+ function buildAgenticPrompt2(params) {
44056
+ if (params.userPrompt) {
44057
+ return params.userPrompt;
44058
+ }
44059
+ const fieldNames = params.fields.map((field) => getFieldName2(field)).filter((name) => Boolean(name));
44060
+ if (fieldNames.length === 0) {
44061
+ return DEFAULT_AGENTIC_PROMPT2;
44062
+ }
44063
+ const fieldList = fieldNames.join(", ");
44064
+ if (params.entity) {
44065
+ return `extract all ${params.entity} entities from this page and return these fields: ${fieldList}`;
44066
+ }
44067
+ return `extract all records from this page and return these fields: ${fieldList}`;
44068
+ }
43951
44069
  function validateEmailChannelConfig(config2) {
43952
44070
  const issues = [];
43953
44071
  if (!config2.recipients?.length) {
@@ -44105,11 +44223,11 @@ function createAxiosInstance(params) {
44105
44223
  }
44106
44224
  function createClientDomains(params) {
44107
44225
  const { client } = params;
44226
+ const changesService = new ChangesService(client);
44108
44227
  const userService = new UserService(client);
44109
44228
  const dataFetcherService = new DataFetcherService(client.apis.workflows);
44110
44229
  const channelsService = new NotificationChannelsService(client.apis.notifications, userService);
44111
44230
  const settingsService = new NotificationSettingsService(client.apis.notifications);
44112
- const entityResolverService = new EntityResolverService(client);
44113
44231
  const workflowsCoreService = new WorkflowsCoreService(client.apis.workflows);
44114
44232
  const schemasService = new SchemasService(client);
44115
44233
  const templatesService = new TemplatesService(client);
@@ -44117,8 +44235,8 @@ function createClientDomains(params) {
44117
44235
  const channelSetupService = new NotificationSetupService(channelsService, settingsService);
44118
44236
  const coreService = new ValidationCoreService(client);
44119
44237
  const rulesService = new ValidationRulesService(client);
44120
- const extractionService = new ExtractionService(workflowsCoreService, dataFetcherService, entityResolverService, channelSetupService, channelsService, settingsService);
44121
- const extractionBuilderService = new ExtractionBuilderService(workflowsCoreService, entityResolverService, dataFetcherService, channelSetupService);
44238
+ const extractionService = new ExtractionService(workflowsCoreService, dataFetcherService, channelSetupService, channelsService, settingsService);
44239
+ const extractionBuilderService = new ExtractionBuilderService(workflowsCoreService, dataFetcherService, channelSetupService);
44122
44240
  const notification = createNotificationDomain({
44123
44241
  notificationsApi: client.apis.notifications,
44124
44242
  channelsService,
@@ -44128,6 +44246,7 @@ function createClientDomains(params) {
44128
44246
  const validation = createValidationDomain(coreService, rulesService);
44129
44247
  const crawler = createCrawlerDomain(client);
44130
44248
  return {
44249
+ changes: changesService,
44131
44250
  extractionBuilderService,
44132
44251
  extraction: extractionService,
44133
44252
  workflow: workflowsCoreService,
@@ -44177,7 +44296,31 @@ function createNotificationDomain(params) {
44177
44296
  }
44178
44297
  };
44179
44298
  }
44180
- var import_debug, __require2, BASE_PATH, BaseAPI = class {
44299
+ var import_debug, __require2, ChangeDifferenceType, KadoaErrorCode, _KadoaSdkException, KadoaSdkException, ERROR_MESSAGES, KadoaHttpException, createLogger = (namespace) => import_debug.default(`kadoa:${namespace}`), logger, debug, ChangesService = class {
44300
+ constructor(client) {
44301
+ this.client = client;
44302
+ }
44303
+ get workflowsApi() {
44304
+ return this.client.apis.workflows;
44305
+ }
44306
+ async list(options) {
44307
+ debug("list changes %o", options);
44308
+ const response = await this.workflowsApi.v4ChangesGet(options ?? {});
44309
+ return mapListChangesResponse(response.data);
44310
+ }
44311
+ async get(changeId) {
44312
+ debug("get change %s", changeId);
44313
+ const response = await this.workflowsApi.v4ChangesChangeIdGet({ changeId });
44314
+ const change = response.data;
44315
+ if (!change) {
44316
+ throw new KadoaSdkException(`Change not found: ${changeId}`, {
44317
+ code: KadoaErrorCode.NOT_FOUND,
44318
+ details: { changeId }
44319
+ });
44320
+ }
44321
+ return mapChange(change);
44322
+ }
44323
+ }, BASE_PATH, BaseAPI = class {
44181
44324
  constructor(configuration, basePath = BASE_PATH, axios2 = axios_default) {
44182
44325
  this.basePath = basePath;
44183
44326
  this.axios = axios2;
@@ -47261,12 +47404,19 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47261
47404
  yield page;
47262
47405
  }
47263
47406
  }
47264
- }, KadoaErrorCode, _KadoaSdkException, KadoaSdkException, ERROR_MESSAGES, KadoaHttpException, createLogger = (namespace) => import_debug.default(`kadoa:${namespace}`), logger, _SchemaBuilder = class _SchemaBuilder2 {
47407
+ }, RAW_HELPER_FIELD_CONFIG, _SchemaBuilder = class _SchemaBuilder2 {
47265
47408
  constructor() {
47266
47409
  this.fields = [];
47267
47410
  }
47268
- hasSchemaFields() {
47269
- return this.fields.some((field) => field.fieldType === "SCHEMA");
47411
+ isRawHelperField(field) {
47412
+ return field.fieldType === "SCHEMA" && field.name in {
47413
+ rawHtml: true,
47414
+ rawMarkdown: true,
47415
+ rawPageUrl: true
47416
+ };
47417
+ }
47418
+ hasEntityRequiringSchemaFields() {
47419
+ return this.fields.some((field) => field.fieldType === "SCHEMA" && !this.isRawHelperField(field));
47270
47420
  }
47271
47421
  entity(entityName) {
47272
47422
  this.entityName = entityName;
@@ -47302,20 +47452,23 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47302
47452
  const names = Array.isArray(name) ? name : [name];
47303
47453
  for (const name2 of names) {
47304
47454
  const fieldName = `raw${upperFirst(camelCase(name2))}`;
47455
+ const rawKey = name2.toUpperCase();
47456
+ const config2 = RAW_HELPER_FIELD_CONFIG[rawKey];
47305
47457
  if (this.fields.some((field) => field.name === fieldName)) {
47306
47458
  continue;
47307
47459
  }
47308
47460
  this.fields.push({
47309
47461
  name: fieldName,
47310
- description: `Raw page content in ${name2.toUpperCase()} format`,
47311
- fieldType: "METADATA",
47312
- metadataKey: name2
47462
+ description: config2.description,
47463
+ fieldType: "SCHEMA",
47464
+ dataType: config2.dataType,
47465
+ example: config2.example
47313
47466
  });
47314
47467
  }
47315
47468
  return this;
47316
47469
  }
47317
47470
  build() {
47318
- if (this.hasSchemaFields() && !this.entityName) {
47471
+ if (this.hasEntityRequiringSchemaFields() && !this.entityName) {
47319
47472
  throw new KadoaSdkException("Entity name is required when schema fields are present", {
47320
47473
  code: "VALIDATION_ERROR",
47321
47474
  details: { entityName: this.entityName }
@@ -47341,7 +47494,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47341
47494
  });
47342
47495
  }
47343
47496
  }
47344
- }, SchemaBuilder, debug, SchemasService = class {
47497
+ }, SchemaBuilder, debug2, SchemasService = class {
47345
47498
  constructor(client) {
47346
47499
  this.client = client;
47347
47500
  }
@@ -47376,7 +47529,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47376
47529
  };
47377
47530
  }
47378
47531
  async getSchema(schemaId) {
47379
- debug("Fetching schema with ID: %s", schemaId);
47532
+ debug2("Fetching schema with ID: %s", schemaId);
47380
47533
  const response = await this.schemasApi.v4SchemasSchemaIdGet({
47381
47534
  schemaId
47382
47535
  });
@@ -47394,7 +47547,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47394
47547
  return response.data.data;
47395
47548
  }
47396
47549
  async createSchema(body) {
47397
- debug("Creating schema with name: %s", body.name);
47550
+ debug2("Creating schema with name: %s", body.name);
47398
47551
  const response = await this.schemasApi.v4SchemasPost({
47399
47552
  createSchemaBody: body
47400
47553
  });
@@ -47407,7 +47560,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47407
47560
  return this.getSchema(schemaId);
47408
47561
  }
47409
47562
  async updateSchema(schemaId, body) {
47410
- debug("Updating schema with ID: %s", schemaId);
47563
+ debug2("Updating schema with ID: %s", schemaId);
47411
47564
  await this.schemasApi.v4SchemasSchemaIdPut({
47412
47565
  schemaId,
47413
47566
  updateSchemaBody: body
@@ -47415,93 +47568,15 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47415
47568
  return this.getSchema(schemaId);
47416
47569
  }
47417
47570
  async deleteSchema(schemaId) {
47418
- debug("Deleting schema with ID: %s", schemaId);
47571
+ debug2("Deleting schema with ID: %s", schemaId);
47419
47572
  await this.schemasApi.v4SchemasSchemaIdDelete({
47420
47573
  schemaId
47421
47574
  });
47422
47575
  }
47423
- }, ENTITY_API_ENDPOINT = "/v4/entity", EntityResolverService = class {
47424
- constructor(client) {
47425
- this.client = client;
47426
- this.schemasService = new SchemasService(client);
47427
- }
47428
- async resolveEntity(entityConfig, options) {
47429
- if (entityConfig === "ai-detection") {
47430
- if (!options?.link) {
47431
- throw new KadoaSdkException(ERROR_MESSAGES.LINK_REQUIRED, {
47432
- code: "VALIDATION_ERROR",
47433
- details: { entityConfig, options }
47434
- });
47435
- }
47436
- const entityPrediction = await this.fetchEntityFields({
47437
- link: options.link,
47438
- location: options.location,
47439
- navigationMode: options.navigationMode,
47440
- selectorMode: options.selectorMode ?? false
47441
- });
47442
- const entity = entityPrediction.entity;
47443
- return {
47444
- entity,
47445
- fields: entityPrediction.fields
47446
- };
47447
- } else if (entityConfig) {
47448
- if ("schemaId" in entityConfig) {
47449
- const schema = await this.schemasService.getSchema(entityConfig.schemaId);
47450
- return {
47451
- entity: schema.entity ?? undefined,
47452
- fields: schema.schema
47453
- };
47454
- } else if ("fields" in entityConfig) {
47455
- return {
47456
- entity: entityConfig.name,
47457
- fields: entityConfig.fields
47458
- };
47459
- }
47460
- }
47461
- throw new KadoaSdkException(ERROR_MESSAGES.ENTITY_INVARIANT_VIOLATION, {
47462
- details: {
47463
- entity: entityConfig
47464
- }
47465
- });
47466
- }
47467
- async fetchEntityFields(options) {
47468
- this.validateEntityOptions(options);
47469
- const url3 = `${this.client.baseUrl}${ENTITY_API_ENDPOINT}`;
47470
- const requestBody = options;
47471
- const response = await this.client.axiosInstance.post(url3, requestBody, {
47472
- headers: {
47473
- "Content-Type": "application/json",
47474
- Accept: "application/json",
47475
- "x-api-key": this.client.apiKey
47476
- }
47477
- });
47478
- const data = response.data;
47479
- if (!data.success || !data.entityPrediction || data.entityPrediction.length === 0) {
47480
- throw new KadoaSdkException(ERROR_MESSAGES.NO_PREDICTIONS, {
47481
- code: "NOT_FOUND",
47482
- details: {
47483
- success: data.success,
47484
- hasPredictions: !!data.entityPrediction,
47485
- predictionCount: data.entityPrediction?.length || 0,
47486
- link: options.link
47487
- }
47488
- });
47489
- }
47490
- return data.entityPrediction[0];
47491
- }
47492
- validateEntityOptions(options) {
47493
- if (!options.link) {
47494
- throw new KadoaSdkException(ERROR_MESSAGES.LINK_REQUIRED, {
47495
- code: "VALIDATION_ERROR",
47496
- details: { options }
47497
- });
47498
- }
47499
- }
47500
- }, debug2, SUCCESSFUL_RUN_STATES, DEFAULT_OPTIONS, ExtractionService = class {
47501
- constructor(workflowsCoreService, dataFetcherService, entityResolverService, notificationSetupService, notificationChannelsService, notificationSettingsService) {
47576
+ }, debug3, SUCCESSFUL_RUN_STATES, DEFAULT_AGENTIC_PROMPT = "extract all the data for the main entity of this page", DEFAULT_OPTIONS, ExtractionService = class {
47577
+ constructor(workflowsCoreService, dataFetcherService, notificationSetupService, notificationChannelsService, notificationSettingsService) {
47502
47578
  this.workflowsCoreService = workflowsCoreService;
47503
47579
  this.dataFetcherService = dataFetcherService;
47504
- this.entityResolverService = entityResolverService;
47505
47580
  this.notificationSetupService = notificationSetupService;
47506
47581
  this.notificationChannelsService = notificationChannelsService;
47507
47582
  this.notificationSettingsService = notificationSettingsService;
@@ -47536,7 +47611,9 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47536
47611
  }
47537
47612
  async executeExtraction(options) {
47538
47613
  this.validateOptions(options);
47539
- const config2 = merge3(DEFAULT_OPTIONS, options);
47614
+ const config2 = {
47615
+ ...merge3(DEFAULT_OPTIONS, options)
47616
+ };
47540
47617
  const isRealTime = config2.interval === "REAL_TIME";
47541
47618
  if (isRealTime) {
47542
47619
  throw new KadoaSdkException("extraction.run()/submit() are not supported for real-time workflows. Use the builder API, call waitForReady(), and subscribe via client.realtime.onEvent(...).", {
@@ -47547,35 +47624,23 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47547
47624
  });
47548
47625
  }
47549
47626
  let workflowId;
47550
- const isAgenticNavigation = config2.navigationMode === "agentic-navigation";
47551
- if (isAgenticNavigation) {
47552
- if (!config2.userPrompt) {
47553
- throw new KadoaSdkException("userPrompt is required when navigationMode is 'agentic-navigation'", {
47554
- code: "VALIDATION_ERROR",
47555
- details: { navigationMode: config2.navigationMode }
47556
- });
47557
- }
47558
- }
47559
- let resolvedEntity;
47560
- if (isAgenticNavigation) {
47561
- const entityConfig = options.entity || "ai-detection";
47562
- resolvedEntity = {
47563
- entity: typeof entityConfig === "object" && "name" in entityConfig ? entityConfig.name : undefined,
47564
- fields: typeof entityConfig === "object" && "fields" in entityConfig ? entityConfig.fields : []
47565
- };
47566
- } else {
47567
- resolvedEntity = await this.entityResolverService.resolveEntity(options.entity || "ai-detection", {
47568
- link: config2.urls[0],
47569
- location: config2.location,
47570
- navigationMode: config2.navigationMode
47571
- });
47572
- }
47627
+ const entityConfig = options.entity;
47628
+ const resolvedEntity = {
47629
+ entity: typeof entityConfig === "object" && "name" in entityConfig ? entityConfig.name : undefined,
47630
+ fields: typeof entityConfig === "object" && "fields" in entityConfig ? entityConfig.fields : []
47631
+ };
47573
47632
  const hasNotifications = !!config2.notifications;
47633
+ const userPrompt = buildAgenticPrompt({
47634
+ entity: resolvedEntity.entity,
47635
+ fields: resolvedEntity.fields,
47636
+ userPrompt: config2.userPrompt
47637
+ });
47574
47638
  const workflowRequest = {
47575
47639
  ...config2,
47640
+ navigationMode: "agentic-navigation",
47576
47641
  fields: resolvedEntity.fields,
47577
47642
  ...resolvedEntity.entity !== undefined ? { entity: resolvedEntity.entity } : {},
47578
- ...config2.userPrompt ? { userPrompt: config2.userPrompt } : {}
47643
+ userPrompt
47579
47644
  };
47580
47645
  const result = await this.workflowsCoreService.create(workflowRequest);
47581
47646
  workflowId = result.id;
@@ -47585,7 +47650,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47585
47650
  events: config2.notifications?.events,
47586
47651
  channels: config2.notifications?.channels
47587
47652
  });
47588
- debug2("Notifications setup: %O", result2.map((r) => ({ id: r.id, eventType: r.eventType })));
47653
+ debug3("Notifications setup: %O", result2.map((r) => ({ id: r.id, eventType: r.eventType })));
47589
47654
  }
47590
47655
  if (config2.mode === "submit") {
47591
47656
  return {
@@ -47660,10 +47725,9 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47660
47725
  isExtractionSuccessful(runState) {
47661
47726
  return runState ? SUCCESSFUL_RUN_STATES.has(runState.toUpperCase()) : false;
47662
47727
  }
47663
- }, debug3, ExtractionBuilderService = class {
47664
- constructor(workflowsCoreService, entityResolverService, dataFetcherService, notificationSetupService) {
47728
+ }, debug4, DEFAULT_AGENTIC_PROMPT2 = "extract all the data for the main entity of this page", BUILD_NOT_READY_ERROR = "No completed build. Build the project first.", TERMINAL_RUN_STATES, ExtractionBuilderService = class {
47729
+ constructor(workflowsCoreService, dataFetcherService, notificationSetupService) {
47665
47730
  this.workflowsCoreService = workflowsCoreService;
47666
- this.entityResolverService = entityResolverService;
47667
47731
  this.dataFetcherService = dataFetcherService;
47668
47732
  this.notificationSetupService = notificationSetupService;
47669
47733
  }
@@ -47689,7 +47753,6 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47689
47753
  urls,
47690
47754
  name,
47691
47755
  description,
47692
- navigationMode,
47693
47756
  extraction,
47694
47757
  additionalData,
47695
47758
  bypassPreview,
@@ -47699,23 +47762,22 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47699
47762
  location
47700
47763
  }) {
47701
47764
  let entity = "ai-detection";
47765
+ let builtFields = [];
47702
47766
  if (extraction) {
47703
47767
  const result = extraction(new SchemaBuilder);
47704
47768
  if ("schemaId" in result) {
47705
47769
  entity = { schemaId: result.schemaId };
47706
47770
  } else {
47707
47771
  const builtSchema = result.build();
47708
- entity = builtSchema.entityName ? { name: builtSchema.entityName, fields: builtSchema.fields } : { fields: builtSchema.fields };
47772
+ builtFields = builtSchema.fields;
47773
+ entity = builtSchema.entityName ? { name: builtSchema.entityName, fields: builtFields } : { fields: builtFields };
47709
47774
  }
47710
47775
  }
47711
- if (userPrompt) {
47712
- this._userPrompt = userPrompt;
47713
- }
47776
+ this._userPrompt = userPrompt;
47714
47777
  this._options = {
47715
47778
  urls,
47716
47779
  name,
47717
47780
  description,
47718
- navigationMode: navigationMode || "single-page",
47719
47781
  entity,
47720
47782
  bypassPreview: bypassPreview ?? false,
47721
47783
  additionalData,
@@ -47762,41 +47824,27 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47762
47824
  }
47763
47825
  async create() {
47764
47826
  assert2(this._options, "Options are not set");
47765
- const { urls, name, description, navigationMode, entity } = this.options;
47766
- const isAgenticNavigation = navigationMode === "agentic-navigation";
47767
- if (isAgenticNavigation) {
47768
- if (!this._userPrompt) {
47769
- throw new KadoaSdkException("userPrompt is required when navigationMode is 'agentic-navigation'", {
47770
- code: "VALIDATION_ERROR",
47771
- details: { navigationMode }
47772
- });
47773
- }
47774
- }
47775
- const isRealTime = this._options.interval === "REAL_TIME";
47776
- const useSelectorMode = isRealTime && entity === "ai-detection";
47777
- let resolvedEntity;
47778
- if (isAgenticNavigation) {
47779
- resolvedEntity = {
47780
- entity: typeof entity === "object" && "name" in entity ? entity.name : undefined,
47781
- fields: typeof entity === "object" && "fields" in entity ? entity.fields : []
47782
- };
47783
- } else {
47784
- resolvedEntity = await this.entityResolverService.resolveEntity(entity, {
47785
- link: urls[0],
47786
- location: this._options.location,
47787
- navigationMode,
47788
- selectorMode: useSelectorMode
47789
- });
47790
- }
47791
- const hasSchemaId = typeof entity === "object" && "schemaId" in entity && entity.schemaId;
47827
+ const { urls, name, description, entity } = this.options;
47828
+ const resolvedEntity = {
47829
+ entity: typeof entity === "object" && "name" in entity ? entity.name : undefined,
47830
+ fields: typeof entity === "object" && "fields" in entity ? entity.fields : []
47831
+ };
47832
+ this._userPrompt = buildAgenticPrompt2({
47833
+ entity: resolvedEntity.entity,
47834
+ fields: resolvedEntity.fields,
47835
+ userPrompt: this._userPrompt
47836
+ });
47837
+ this._options.userPrompt = this._userPrompt;
47838
+ const schemaId = typeof entity === "object" && "schemaId" in entity ? entity.schemaId : undefined;
47839
+ const hasSchemaId = Boolean(schemaId);
47792
47840
  const workflow = await this.workflowsCoreService.create({
47793
47841
  urls,
47794
47842
  name,
47795
47843
  description,
47796
- navigationMode,
47844
+ navigationMode: "agentic-navigation",
47797
47845
  monitoring: this._monitoringOptions,
47798
47846
  ...hasSchemaId ? {
47799
- schemaId: entity.schemaId,
47847
+ schemaId,
47800
47848
  entity: resolvedEntity.entity,
47801
47849
  fields: resolvedEntity.fields
47802
47850
  } : { entity: resolvedEntity.entity, fields: resolvedEntity.fields },
@@ -47842,12 +47890,15 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47842
47890
  }
47843
47891
  });
47844
47892
  }
47845
- const startedJob = await this.workflowsCoreService.runWorkflow(this._workflowId, { variables: options?.variables, limit: options?.limit });
47893
+ const startedJob = await this.startOrReuseWorkflowRun(this._workflowId, {
47894
+ variables: options?.variables,
47895
+ limit: options?.limit
47896
+ });
47846
47897
  assert2(startedJob.jobId, "Job ID is not set");
47847
- debug3("Job started: %O", startedJob);
47898
+ debug4("Job started: %O", startedJob);
47848
47899
  this._jobId = startedJob.jobId;
47849
47900
  const finishedJob = await this.workflowsCoreService.waitForJobCompletion(this._workflowId, startedJob.jobId);
47850
- debug3("Job finished: %O", finishedJob);
47901
+ debug4("Job finished: %O", finishedJob);
47851
47902
  return this;
47852
47903
  }
47853
47904
  async submit(options) {
@@ -47862,9 +47913,12 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47862
47913
  }
47863
47914
  });
47864
47915
  }
47865
- const submittedJob = await this.workflowsCoreService.runWorkflow(this._workflowId, { variables: options?.variables, limit: options?.limit });
47916
+ const submittedJob = await this.startOrReuseWorkflowRun(this._workflowId, {
47917
+ variables: options?.variables,
47918
+ limit: options?.limit
47919
+ });
47866
47920
  assert2(submittedJob.jobId, "Job ID is not set");
47867
- debug3("Job submitted: %O", submittedJob);
47921
+ debug4("Job submitted: %O", submittedJob);
47868
47922
  this._jobId = submittedJob.jobId;
47869
47923
  return {
47870
47924
  workflowId: this._workflowId,
@@ -47891,6 +47945,60 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
47891
47945
  ...options
47892
47946
  });
47893
47947
  }
47948
+ async startOrReuseWorkflowRun(workflowId, input) {
47949
+ const currentJob = await this.findActiveWorkflowJob(workflowId);
47950
+ if (currentJob) {
47951
+ debug4("Reusing active workflow job: %O", currentJob);
47952
+ return currentJob;
47953
+ }
47954
+ try {
47955
+ return await this.workflowsCoreService.runWorkflow(workflowId, input);
47956
+ } catch (error48) {
47957
+ if (!this.isBuildNotReadyError(error48)) {
47958
+ throw error48;
47959
+ }
47960
+ const recoveredJob = await this.waitForWorkflowJob(workflowId);
47961
+ if (recoveredJob) {
47962
+ debug4("Recovered active workflow job after run rejection: %O", recoveredJob);
47963
+ return recoveredJob;
47964
+ }
47965
+ throw error48;
47966
+ }
47967
+ }
47968
+ async findActiveWorkflowJob(workflowId) {
47969
+ const workflow = await this.workflowsCoreService.get(workflowId);
47970
+ if (!workflow.jobId || !workflow.runState) {
47971
+ return;
47972
+ }
47973
+ if (TERMINAL_RUN_STATES.has(workflow.runState.toUpperCase())) {
47974
+ return;
47975
+ }
47976
+ return {
47977
+ jobId: workflow.jobId,
47978
+ status: workflow.runState,
47979
+ message: "Workflow already has an active run"
47980
+ };
47981
+ }
47982
+ async waitForWorkflowJob(workflowId) {
47983
+ for (let attempt2 = 0;attempt2 < 5; attempt2 += 1) {
47984
+ const currentJob = await this.findActiveWorkflowJob(workflowId);
47985
+ if (currentJob) {
47986
+ return currentJob;
47987
+ }
47988
+ await new Promise((resolve) => setTimeout(resolve, 1000));
47989
+ }
47990
+ return;
47991
+ }
47992
+ isBuildNotReadyError(error48) {
47993
+ if (!(error48 instanceof KadoaHttpException)) {
47994
+ return false;
47995
+ }
47996
+ const responseBody = error48.responseBody;
47997
+ if (responseBody && typeof responseBody === "object" && "error" in responseBody && typeof responseBody.error === "string") {
47998
+ return responseBody.error.includes(BUILD_NOT_READY_ERROR);
47999
+ }
48000
+ return typeof error48.message === "string" ? error48.message.includes(BUILD_NOT_READY_ERROR) : false;
48001
+ }
47894
48002
  }, NotificationChannelType, EMAIL_REGEX, _NotificationChannelsService = class _NotificationChannelsService2 {
47895
48003
  constructor(notificationsApi, userService) {
47896
48004
  this.api = notificationsApi;
@@ -48048,7 +48156,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48048
48156
  });
48049
48157
  }
48050
48158
  }
48051
- }, debug4, NotificationSetupService = class {
48159
+ }, debug5, NotificationSetupService = class {
48052
48160
  constructor(channelsService, settingsService) {
48053
48161
  this.channelsService = channelsService;
48054
48162
  this.settingsService = settingsService;
@@ -48073,7 +48181,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48073
48181
  });
48074
48182
  }
48075
48183
  async setup(requestData) {
48076
- requestData.workflowId ? debug4("Setting up notifications for workflow %s", requestData.workflowId) : debug4("Setting up notifications for workspace");
48184
+ requestData.workflowId ? debug5("Setting up notifications for workflow %s", requestData.workflowId) : debug5("Setting up notifications for workspace");
48077
48185
  const channels = await this.setupChannels({
48078
48186
  workflowId: requestData.workflowId,
48079
48187
  channels: requestData.channels || {}
@@ -48081,7 +48189,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48081
48189
  const events = requestData.events || "all";
48082
48190
  const eventTypes = events === "all" ? await this.settingsService.listAllEvents() : events;
48083
48191
  const channelIds = channels.map((channel) => channel.id).filter(Boolean);
48084
- debug4("Creating notification settings for workflow %s: %O", requestData.workflowId, {
48192
+ debug5("Creating notification settings for workflow %s: %O", requestData.workflowId, {
48085
48193
  events: eventTypes,
48086
48194
  channels: channelIds
48087
48195
  });
@@ -48108,7 +48216,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48108
48216
  eventConfiguration: {}
48109
48217
  });
48110
48218
  }));
48111
- debug4(requestData.workflowId ? "Successfully setup notifications for workflow %s" : "Successfully setup notifications for workspace", requestData.workflowId);
48219
+ debug5(requestData.workflowId ? "Successfully setup notifications for workflow %s" : "Successfully setup notifications for workspace", requestData.workflowId);
48112
48220
  return newSettings;
48113
48221
  }
48114
48222
  async setupChannels(requestData) {
@@ -48165,7 +48273,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48165
48273
  const channels = await Promise.all(channelsByName.map(async ([channelType]) => {
48166
48274
  const existingChannel = channelType === NotificationChannelType.WEBSOCKET ? existingChannels.find((channel2) => channel2.channelType === channelType) : existingChannels.find((channel2) => channel2.channelType === channelType && channel2.name === NotificationChannelsService.DEFAULT_CHANNEL_NAME);
48167
48275
  if (existingChannel) {
48168
- debug4("Using existing default channel: %O", {
48276
+ debug5("Using existing default channel: %O", {
48169
48277
  workflowId,
48170
48278
  channelType,
48171
48279
  channelId: existingChannel.id
@@ -48173,7 +48281,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48173
48281
  return existingChannel;
48174
48282
  }
48175
48283
  const channel = await this.channelsService.createChannel(channelType);
48176
- debug4("Created default channel %O", {
48284
+ debug5("Created default channel %O", {
48177
48285
  workflowId,
48178
48286
  channelType,
48179
48287
  channel
@@ -48194,7 +48302,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48194
48302
  const channelName = config2.name || NotificationChannelsService.DEFAULT_CHANNEL_NAME;
48195
48303
  const existingChannel = existingChannels.find((channel2) => channel2.channelType === channelType && (channel2.name || NotificationChannelsService.DEFAULT_CHANNEL_NAME) === channelName);
48196
48304
  if (existingChannel) {
48197
- debug4("Using existing channel: %O", {
48305
+ debug5("Using existing channel: %O", {
48198
48306
  workflowId,
48199
48307
  channelType,
48200
48308
  channelName,
@@ -48207,7 +48315,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48207
48315
  name: channelName,
48208
48316
  config: channelConfig
48209
48317
  });
48210
- debug4("Created channel with custom config %O", {
48318
+ debug5("Created channel with custom config %O", {
48211
48319
  workflowId,
48212
48320
  channelType,
48213
48321
  channelName,
@@ -48217,7 +48325,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48217
48325
  }));
48218
48326
  return channels;
48219
48327
  }
48220
- }, PUBLIC_API_URI, WSS_API_URI, REALTIME_API_URI, SDK_VERSION = "0.26.0", SDK_NAME = "kadoa-node-sdk", SDK_LANGUAGE = "node", debug5, isDrainControlMessage = (message) => message.type === "control.draining", isRealtimeEvent = (message) => message.type !== "heartbeat" && message.type !== "control.draining", _Realtime = class _Realtime2 {
48328
+ }, PUBLIC_API_URI, WSS_API_URI, REALTIME_API_URI, SDK_VERSION = "0.28.0", SDK_NAME = "kadoa-node-sdk", SDK_LANGUAGE = "node", debug6, isDrainControlMessage = (message) => message.type === "control.draining", isRealtimeEvent = (message) => message.type !== "heartbeat" && message.type !== "control.draining", _Realtime = class _Realtime2 {
48221
48329
  constructor(config2) {
48222
48330
  this.drainingSockets = /* @__PURE__ */ new Set;
48223
48331
  this.lastHeartbeat = Date.now();
@@ -48245,7 +48353,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48245
48353
  await this.openSocket(access_token, team_id, "active");
48246
48354
  this.hasConnectedOnce = true;
48247
48355
  } catch (err) {
48248
- debug5("Failed to connect: %O", err);
48356
+ debug6("Failed to connect: %O", err);
48249
48357
  this.isConnecting = false;
48250
48358
  this.notifyErrorListeners(err);
48251
48359
  if (!this.hasConnectedOnce) {
@@ -48282,7 +48390,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48282
48390
  this.isConnecting = false;
48283
48391
  this.lastHeartbeat = Date.now();
48284
48392
  this.startHeartbeatCheck();
48285
- debug5("Connected to WebSocket");
48393
+ debug6("Connected to WebSocket");
48286
48394
  if (!settled) {
48287
48395
  settled = true;
48288
48396
  resolve();
@@ -48347,7 +48455,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48347
48455
  headers: { "Content-Type": "application/json" },
48348
48456
  body: JSON.stringify({ id: data.id })
48349
48457
  }).catch((error48) => {
48350
- debug5("Failed to acknowledge event %s: %O", data.id, error48);
48458
+ debug6("Failed to acknowledge event %s: %O", data.id, error48);
48351
48459
  });
48352
48460
  }
48353
48461
  if (this.isDuplicateEvent(data.id)) {
@@ -48355,14 +48463,14 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48355
48463
  }
48356
48464
  this.notifyEventListeners(data);
48357
48465
  } catch (err) {
48358
- debug5("Failed to parse incoming message: %O", err);
48466
+ debug6("Failed to parse incoming message: %O", err);
48359
48467
  }
48360
48468
  }
48361
48469
  handleDrainSignal(socket, message) {
48362
48470
  if (socket !== this.activeSocket || this.isClosed) {
48363
48471
  return;
48364
48472
  }
48365
- debug5("Received drain signal, preparing replacement socket");
48473
+ debug6("Received drain signal, preparing replacement socket");
48366
48474
  this.drainingSockets.add(socket);
48367
48475
  this.scheduleDrainReconnect(message.retryAfterMs);
48368
48476
  }
@@ -48378,7 +48486,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48378
48486
  return;
48379
48487
  }
48380
48488
  if (this.drainingSockets.size > 0) {
48381
- debug5("Draining socket closed after replacement was scheduled");
48489
+ debug6("Draining socket closed after replacement was scheduled");
48382
48490
  return;
48383
48491
  }
48384
48492
  this.handleUnexpectedDisconnect("Connection closed");
@@ -48402,7 +48510,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48402
48510
  const { access_token, team_id } = await this.getOAuthToken();
48403
48511
  await this.openSocket(access_token, team_id, replacement ? "replacement" : "active");
48404
48512
  } catch (err) {
48405
- debug5("Reconnect failed: %O", err);
48513
+ debug6("Reconnect failed: %O", err);
48406
48514
  this.isConnecting = false;
48407
48515
  this.notifyErrorListeners(err);
48408
48516
  this.scheduleReconnect(replacement);
@@ -48427,7 +48535,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48427
48535
  const { access_token, team_id } = await this.getOAuthToken();
48428
48536
  await this.openSocket(access_token, team_id, "replacement");
48429
48537
  } catch (err) {
48430
- debug5("Reconnect failed: %O", err);
48538
+ debug6("Reconnect failed: %O", err);
48431
48539
  this.isConnecting = false;
48432
48540
  this.notifyErrorListeners(err);
48433
48541
  this.scheduleReconnect(true);
@@ -48458,7 +48566,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48458
48566
  return false;
48459
48567
  }
48460
48568
  handleHeartbeat() {
48461
- debug5("Heartbeat received");
48569
+ debug6("Heartbeat received");
48462
48570
  this.lastHeartbeat = Date.now();
48463
48571
  }
48464
48572
  notifyEventListeners(event) {
@@ -48466,7 +48574,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48466
48574
  try {
48467
48575
  listener(event);
48468
48576
  } catch (error48) {
48469
- debug5("Error in event listener: %O", error48);
48577
+ debug6("Error in event listener: %O", error48);
48470
48578
  }
48471
48579
  });
48472
48580
  }
@@ -48475,7 +48583,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48475
48583
  try {
48476
48584
  listener(connected, reason);
48477
48585
  } catch (error48) {
48478
- debug5("Error in connection listener: %O", error48);
48586
+ debug6("Error in connection listener: %O", error48);
48479
48587
  }
48480
48588
  });
48481
48589
  }
@@ -48484,7 +48592,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48484
48592
  try {
48485
48593
  listener(error48);
48486
48594
  } catch (listenerError) {
48487
- debug5("Error in error listener: %O", listenerError);
48595
+ debug6("Error in error listener: %O", listenerError);
48488
48596
  }
48489
48597
  });
48490
48598
  }
@@ -48492,7 +48600,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48492
48600
  this.stopHeartbeatCheck();
48493
48601
  this.missedHeartbeatCheckTimer = setInterval(() => {
48494
48602
  if (this.activeSocket && Date.now() - this.lastHeartbeat > this.missedHeartbeatsLimit) {
48495
- debug5("No heartbeat received in 30 seconds! Closing connection.");
48603
+ debug6("No heartbeat received in 30 seconds! Closing connection.");
48496
48604
  this.activeSocket.close();
48497
48605
  }
48498
48606
  }, this.heartbeatInterval);
@@ -48545,7 +48653,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48545
48653
  isConnected() {
48546
48654
  return this.activeSocket?.readyState === WebSocket.OPEN;
48547
48655
  }
48548
- }, Realtime, debug6, TemplatesService = class {
48656
+ }, Realtime, debug7, TemplatesService = class {
48549
48657
  constructor(client) {
48550
48658
  this.client = client;
48551
48659
  }
@@ -48553,12 +48661,12 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48553
48661
  return this.client.apis.templates;
48554
48662
  }
48555
48663
  async list() {
48556
- debug6("Listing all templates");
48664
+ debug7("Listing all templates");
48557
48665
  const response = await this.templatesApi.v4TemplatesGet();
48558
48666
  return response.data.data ?? [];
48559
48667
  }
48560
48668
  async get(templateId) {
48561
- debug6("Fetching template with ID: %s", templateId);
48669
+ debug7("Fetching template with ID: %s", templateId);
48562
48670
  const response = await this.templatesApi.v4TemplatesTemplateIdGet({
48563
48671
  templateId
48564
48672
  });
@@ -48572,7 +48680,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48572
48680
  return template;
48573
48681
  }
48574
48682
  async create(body) {
48575
- debug6("Creating template with name: %s", body.name);
48683
+ debug7("Creating template with name: %s", body.name);
48576
48684
  const response = await this.templatesApi.v4TemplatesPost({
48577
48685
  createTemplateBody: body
48578
48686
  });
@@ -48585,7 +48693,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48585
48693
  return template;
48586
48694
  }
48587
48695
  async update(templateId, body) {
48588
- debug6("Updating template with ID: %s", templateId);
48696
+ debug7("Updating template with ID: %s", templateId);
48589
48697
  const response = await this.templatesApi.v4TemplatesTemplateIdPut({
48590
48698
  templateId,
48591
48699
  updateTemplateBody: body
@@ -48600,13 +48708,13 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48600
48708
  return template;
48601
48709
  }
48602
48710
  async delete(templateId) {
48603
- debug6("Deleting template with ID: %s", templateId);
48711
+ debug7("Deleting template with ID: %s", templateId);
48604
48712
  await this.templatesApi.v4TemplatesTemplateIdDelete({
48605
48713
  templateId
48606
48714
  });
48607
48715
  }
48608
48716
  async createVersion(templateId, body) {
48609
- debug6("Creating version for template: %s", templateId);
48717
+ debug7("Creating version for template: %s", templateId);
48610
48718
  const response = await this.templatesApi.v4TemplatesTemplateIdVersionsPost({
48611
48719
  templateId,
48612
48720
  createTemplateVersionBody: body
@@ -48621,45 +48729,14 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48621
48729
  return version2;
48622
48730
  }
48623
48731
  async listSchemas(templateId) {
48624
- debug6("Listing schemas for template: %s", templateId);
48732
+ debug7("Listing schemas for template: %s", templateId);
48625
48733
  const response = await this.templatesApi.v4TemplatesTemplateIdSchemasGet({
48626
48734
  templateId
48627
48735
  });
48628
48736
  return response.data.data ?? [];
48629
48737
  }
48630
- async listWorkflows(templateId) {
48631
- debug6("Listing workflows for template: %s", templateId);
48632
- const response = await this.templatesApi.v4TemplatesTemplateIdWorkflowsGet({
48633
- templateId
48634
- });
48635
- return response.data.data ?? [];
48636
- }
48637
- async linkWorkflows(templateId, body) {
48638
- debug6("Linking %d workflows to template: %s", body.workflowIds.length, templateId);
48639
- const response = await this.templatesApi.v4TemplatesTemplateIdLinkPost({
48640
- templateId,
48641
- linkWorkflowsBody: body
48642
- });
48643
- return response.data;
48644
- }
48645
- async unlinkWorkflows(templateId, body) {
48646
- debug6("Unlinking %d workflows from template: %s", body.workflowIds.length, templateId);
48647
- const response = await this.templatesApi.v4TemplatesTemplateIdUnlinkPost({
48648
- templateId,
48649
- unlinkWorkflowsBody: body
48650
- });
48651
- return response.data;
48652
- }
48653
- async applyUpdate(templateId, body) {
48654
- debug6("Applying version %d to %d workflows for template: %s", body.targetVersion, body.workflowIds.length, templateId);
48655
- const response = await this.templatesApi.v4TemplatesTemplateIdApplyPost({
48656
- templateId,
48657
- applyTemplateUpdateBody: body
48658
- });
48659
- return response.data;
48660
- }
48661
48738
  async createFromWorkflow(body) {
48662
- debug6("Creating template from workflow: %s", body.workflowId);
48739
+ debug7("Creating template from workflow: %s", body.workflowId);
48663
48740
  const response = await this.templatesApi.v4TemplatesFromWorkflowPost({
48664
48741
  saveFromWorkflowBody: body
48665
48742
  });
@@ -48917,7 +48994,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48917
48994
  }
48918
48995
  return response.data.data;
48919
48996
  }
48920
- }, debug7, VariablesService = class {
48997
+ }, debug8, VariablesService = class {
48921
48998
  constructor(client) {
48922
48999
  this.client = client;
48923
49000
  }
@@ -48929,7 +49006,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48929
49006
  return response.data.variables ?? [];
48930
49007
  }
48931
49008
  async get(variableId) {
48932
- debug7("Fetching variable with ID: %s", variableId);
49009
+ debug8("Fetching variable with ID: %s", variableId);
48933
49010
  const response = await this.variablesApi.v4VariablesVariableIdGet({
48934
49011
  variableId
48935
49012
  });
@@ -48943,7 +49020,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48943
49020
  return variable;
48944
49021
  }
48945
49022
  async create(body) {
48946
- debug7("Creating variable with key: %s", body.key);
49023
+ debug8("Creating variable with key: %s", body.key);
48947
49024
  const response = await this.variablesApi.v4VariablesPost({
48948
49025
  createVariableBody: body
48949
49026
  });
@@ -48956,7 +49033,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48956
49033
  return variable;
48957
49034
  }
48958
49035
  async update(variableId, body) {
48959
- debug7("Updating variable with ID: %s", variableId);
49036
+ debug8("Updating variable with ID: %s", variableId);
48960
49037
  const response = await this.variablesApi.v4VariablesVariableIdPatch({
48961
49038
  variableId,
48962
49039
  updateVariableBody: body
@@ -48971,12 +49048,12 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
48971
49048
  return variable;
48972
49049
  }
48973
49050
  async delete(variableId) {
48974
- debug7("Deleting variable with ID: %s", variableId);
49051
+ debug8("Deleting variable with ID: %s", variableId);
48975
49052
  await this.variablesApi.v4VariablesVariableIdDelete({
48976
49053
  variableId
48977
49054
  });
48978
49055
  }
48979
- }, JobStateEnum, TERMINAL_JOB_STATES, TERMINAL_RUN_STATES, debug8, WorkflowsCoreService = class {
49056
+ }, JobStateEnum, TERMINAL_JOB_STATES, TERMINAL_RUN_STATES2, debug9, WorkflowsCoreService = class {
48980
49057
  constructor(workflowsApi) {
48981
49058
  this.workflowsApi = workflowsApi;
48982
49059
  }
@@ -49092,13 +49169,13 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
49092
49169
  async wait(id, options) {
49093
49170
  const result = await pollUntil(async () => {
49094
49171
  const current = await this.get(id);
49095
- debug8("workflow %s state: %s", id, current.runState);
49172
+ debug9("workflow %s state: %s", id, current.runState);
49096
49173
  return current;
49097
49174
  }, (current) => {
49098
49175
  if (options?.targetState && current.state === options.targetState) {
49099
49176
  return true;
49100
49177
  }
49101
- if (current.runState && TERMINAL_RUN_STATES.has(current.runState.toUpperCase()) && current.state !== "QUEUED") {
49178
+ if (current.runState && TERMINAL_RUN_STATES2.has(current.runState.toUpperCase()) && current.state !== "QUEUED") {
49102
49179
  return true;
49103
49180
  }
49104
49181
  return false;
@@ -49138,7 +49215,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
49138
49215
  async waitForJobCompletion(workflowId, jobId, options) {
49139
49216
  const result = await pollUntil(async () => {
49140
49217
  const current = await this.getJobStatus(workflowId, jobId);
49141
- debug8("workflow run %s state: %s", jobId, current.state);
49218
+ debug9("workflow run %s state: %s", jobId, current.state);
49142
49219
  return current;
49143
49220
  }, (current) => {
49144
49221
  if (options?.targetStatus && current.state === options.targetStatus) {
@@ -49211,6 +49288,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
49211
49288
  });
49212
49289
  this.apis = new ApiRegistry(this._apiKey, this._baseUrl, this._axiosInstance, headers);
49213
49290
  const domains = createClientDomains({ client: this });
49291
+ this.changes = domains.changes;
49214
49292
  this.user = domains.user;
49215
49293
  this.extraction = domains.extraction;
49216
49294
  this.workflow = domains.workflow;
@@ -49300,69 +49378,285 @@ var init_dist2 = __esm(() => {
49300
49378
  return __require.apply(this, arguments);
49301
49379
  throw Error('Dynamic require of "' + x + '" is not supported');
49302
49380
  });
49303
- BASE_PATH = "https://api.kadoa.com".replace(/\/+$/, "");
49304
- RequiredError = class extends Error {
49305
- constructor(field, msg) {
49306
- super(msg);
49307
- this.field = field;
49308
- this.name = "RequiredError";
49309
- }
49381
+ ChangeDifferenceType = {
49382
+ Added: "added",
49383
+ Removed: "removed",
49384
+ Changed: "changed"
49310
49385
  };
49311
- operationServerMap = {};
49312
- CrawlerApi = class extends BaseAPI {
49313
- v4CrawlBucketDataFilenameb64Get(requestParameters, options) {
49314
- return CrawlerApiFp(this.configuration).v4CrawlBucketDataFilenameb64Get(requestParameters.filenameb64, requestParameters.contentType, requestParameters.cacheControl, options).then((request) => request(this.axios, this.basePath));
49315
- }
49316
- v4CrawlConfigConfigIdGet(requestParameters, options) {
49317
- return CrawlerApiFp(this.configuration).v4CrawlConfigConfigIdGet(requestParameters.configId, options).then((request) => request(this.axios, this.basePath));
49318
- }
49319
- v4CrawlConfigDelete(requestParameters = {}, options) {
49320
- return CrawlerApiFp(this.configuration).v4CrawlConfigDelete(requestParameters.deleteCrawlerConfigRequest, options).then((request) => request(this.axios, this.basePath));
49321
- }
49322
- v4CrawlConfigPost(requestParameters = {}, options) {
49323
- return CrawlerApiFp(this.configuration).v4CrawlConfigPost(requestParameters.createCrawlerConfigRequest, options).then((request) => request(this.axios, this.basePath));
49324
- }
49325
- v4CrawlPausePost(requestParameters = {}, options) {
49326
- return CrawlerApiFp(this.configuration).v4CrawlPausePost(requestParameters.pauseCrawlerSessionRequest, options).then((request) => request(this.axios, this.basePath));
49327
- }
49328
- v4CrawlPost(requestParameters = {}, options) {
49329
- return CrawlerApiFp(this.configuration).v4CrawlPost(requestParameters.startCrawlerSessionRequest, options).then((request) => request(this.axios, this.basePath));
49330
- }
49331
- v4CrawlResumePost(requestParameters = {}, options) {
49332
- return CrawlerApiFp(this.configuration).v4CrawlResumePost(requestParameters.resumeCrawlerSessionRequest, options).then((request) => request(this.axios, this.basePath));
49386
+ KadoaErrorCode = {
49387
+ VALIDATION_ERROR: "VALIDATION_ERROR",
49388
+ BAD_REQUEST: "BAD_REQUEST",
49389
+ NOT_FOUND: "NOT_FOUND",
49390
+ INTERNAL_ERROR: "INTERNAL_ERROR"
49391
+ };
49392
+ _KadoaSdkException = class _KadoaSdkException2 extends Error {
49393
+ constructor(message, options) {
49394
+ super(message);
49395
+ this.name = "KadoaSdkException";
49396
+ this.code = options?.code ?? "UNKNOWN";
49397
+ this.details = options?.details;
49398
+ if (options && "cause" in options)
49399
+ this.cause = options.cause;
49400
+ Error.captureStackTrace?.(this, _KadoaSdkException2);
49333
49401
  }
49334
- v4CrawlSessionIdListGet(requestParameters, options) {
49335
- return CrawlerApiFp(this.configuration).v4CrawlSessionIdListGet(requestParameters.sessionId, requestParameters.includeAll, options).then((request) => request(this.axios, this.basePath));
49402
+ static from(error48, details) {
49403
+ if (error48 instanceof _KadoaSdkException2)
49404
+ return error48;
49405
+ const message = error48 instanceof Error ? error48.message : typeof error48 === "string" ? error48 : "Unexpected error";
49406
+ return new _KadoaSdkException2(message, {
49407
+ code: "UNKNOWN",
49408
+ details,
49409
+ cause: error48
49410
+ });
49336
49411
  }
49337
- v4CrawlSessionIdPagesGet(requestParameters, options) {
49338
- return CrawlerApiFp(this.configuration).v4CrawlSessionIdPagesGet(requestParameters.sessionId, requestParameters.currentPage, requestParameters.pageSize, options).then((request) => request(this.axios, this.basePath));
49412
+ toJSON() {
49413
+ return {
49414
+ name: this.name,
49415
+ message: this.message,
49416
+ code: this.code,
49417
+ details: this.details
49418
+ };
49339
49419
  }
49340
- v4CrawlSessionIdPagesPageIdGet(requestParameters, options) {
49341
- return CrawlerApiFp(this.configuration).v4CrawlSessionIdPagesPageIdGet(requestParameters.sessionId, requestParameters.pageId, requestParameters.format, options).then((request) => request(this.axios, this.basePath));
49420
+ toString() {
49421
+ return [this.name, this.code, this.message].filter(Boolean).join(": ");
49342
49422
  }
49343
- v4CrawlSessionIdStatusGet(requestParameters, options) {
49344
- return CrawlerApiFp(this.configuration).v4CrawlSessionIdStatusGet(requestParameters.sessionId, options).then((request) => request(this.axios, this.basePath));
49423
+ toDetailedString() {
49424
+ const parts = [`${this.name}: ${this.message}`, `Code: ${this.code}`];
49425
+ if (this.details && Object.keys(this.details).length > 0) {
49426
+ parts.push(`Details: ${JSON.stringify(this.details, null, 2)}`);
49427
+ }
49428
+ if (this.cause) {
49429
+ parts.push(`Cause: ${this.cause}`);
49430
+ }
49431
+ return parts.join(`
49432
+ `);
49345
49433
  }
49346
- v4CrawlSessionsGet(requestParameters = {}, options) {
49347
- return CrawlerApiFp(this.configuration).v4CrawlSessionsGet(requestParameters.page, requestParameters.pageSize, requestParameters.userId, options).then((request) => request(this.axios, this.basePath));
49434
+ static isInstance(error48) {
49435
+ return error48 instanceof _KadoaSdkException2;
49348
49436
  }
49349
- v4CrawlStartPost(requestParameters = {}, options) {
49350
- return CrawlerApiFp(this.configuration).v4CrawlStartPost(requestParameters.startSessionWithConfigRequest, options).then((request) => request(this.axios, this.basePath));
49437
+ static wrap(error48, extra) {
49438
+ if (error48 instanceof _KadoaSdkException2)
49439
+ return error48;
49440
+ const message = extra?.message || (error48 instanceof Error ? error48.message : typeof error48 === "string" ? error48 : "Unexpected error");
49441
+ return new _KadoaSdkException2(message, {
49442
+ code: "UNKNOWN",
49443
+ details: extra?.details,
49444
+ cause: error48
49445
+ });
49351
49446
  }
49352
49447
  };
49353
- DataValidationApi = class extends BaseAPI {
49354
- v4DataValidationRulesActionsBulkApprovePost(requestParameters = {}, options) {
49355
- return DataValidationApiFp(this.configuration).v4DataValidationRulesActionsBulkApprovePost(requestParameters.bulkApproveRules, options).then((request) => request(this.axios, this.basePath));
49356
- }
49357
- v4DataValidationRulesActionsBulkDeletePost(requestParameters = {}, options) {
49358
- return DataValidationApiFp(this.configuration).v4DataValidationRulesActionsBulkDeletePost(requestParameters.bulkDeleteRules, options).then((request) => request(this.axios, this.basePath));
49359
- }
49360
- v4DataValidationRulesActionsDeleteAllDelete(requestParameters = {}, options) {
49361
- return DataValidationApiFp(this.configuration).v4DataValidationRulesActionsDeleteAllDelete(requestParameters.deleteRuleWithReason, options).then((request) => request(this.axios, this.basePath));
49362
- }
49363
- v4DataValidationRulesActionsGeneratePost(requestParameters = {}, options) {
49364
- return DataValidationApiFp(this.configuration).v4DataValidationRulesActionsGeneratePost(requestParameters.generateRule, options).then((request) => request(this.axios, this.basePath));
49365
- }
49448
+ _KadoaSdkException.ERROR_MESSAGES = {
49449
+ CONFIG_ERROR: "Invalid configuration provided",
49450
+ AUTH_FAILED: "Authentication failed. Please check your API key",
49451
+ RATE_LIMITED: "Rate limit exceeded. Please try again later",
49452
+ NETWORK_ERROR: "Network error occurred",
49453
+ SERVER_ERROR: "Server error occurred",
49454
+ PARSE_ERROR: "Failed to parse response",
49455
+ BAD_REQUEST: "Bad request",
49456
+ ABORTED: "Aborted",
49457
+ NOT_FOUND: "Not found",
49458
+ NO_WORKFLOW_ID: "Failed to start extraction process - no ID received",
49459
+ WORKFLOW_CREATE_FAILED: "Failed to create workflow",
49460
+ WORKFLOW_TIMEOUT: "Workflow processing timed out",
49461
+ WORKFLOW_UNEXPECTED_STATUS: "Extraction completed with unexpected status",
49462
+ PROGRESS_CHECK_FAILED: "Failed to check extraction progress",
49463
+ DATA_FETCH_FAILED: "Failed to retrieve extracted data from workflow",
49464
+ NO_URLS: "At least one URL is required for extraction",
49465
+ NO_API_KEY: "API key is required for entity detection",
49466
+ LINK_REQUIRED: "Link is required for entity field detection",
49467
+ NO_PREDICTIONS: "No entity predictions returned from the API",
49468
+ EXTRACTION_FAILED: "Data extraction failed for the provided URLs",
49469
+ ENTITY_FETCH_FAILED: "Failed to fetch entity fields",
49470
+ ENTITY_INVARIANT_VIOLATION: "No valid entity provided",
49471
+ SCHEMA_NOT_FOUND: "Schema not found",
49472
+ SCHEMA_FETCH_ERROR: "Failed to fetch schema",
49473
+ SCHEMAS_FETCH_ERROR: "Failed to fetch schemas",
49474
+ SCHEMA_CREATE_FAILED: "Failed to create schema",
49475
+ SCHEMA_UPDATE_FAILED: "Failed to update schema",
49476
+ SCHEMA_DELETE_FAILED: "Failed to delete schema",
49477
+ VARIABLE_NOT_FOUND: "Variable not found",
49478
+ VARIABLE_CREATE_FAILED: "Failed to create variable",
49479
+ VARIABLE_UPDATE_FAILED: "Failed to update variable",
49480
+ TEMPLATE_NOT_FOUND: "Template not found",
49481
+ TEMPLATE_CREATE_FAILED: "Failed to create template",
49482
+ TEMPLATE_UPDATE_FAILED: "Failed to update template",
49483
+ TEMPLATE_VERSION_CREATE_FAILED: "Failed to create template version",
49484
+ TEMPLATE_FROM_WORKFLOW_FAILED: "Failed to create template from workflow"
49485
+ };
49486
+ KadoaSdkException = _KadoaSdkException;
49487
+ ERROR_MESSAGES = KadoaSdkException.ERROR_MESSAGES;
49488
+ KadoaHttpException = class _KadoaHttpException extends KadoaSdkException {
49489
+ constructor(message, options) {
49490
+ super(message, {
49491
+ code: options?.code,
49492
+ details: options?.details,
49493
+ cause: options?.cause
49494
+ });
49495
+ this.name = "KadoaHttpException";
49496
+ this.httpStatus = options?.httpStatus;
49497
+ this.requestId = options?.requestId;
49498
+ this.endpoint = options?.endpoint;
49499
+ this.method = options?.method;
49500
+ this.responseBody = options?.responseBody;
49501
+ }
49502
+ static fromAxiosError(error48, extra) {
49503
+ const status = error48.response?.status;
49504
+ const requestId = error48.response?.headers?.["x-request-id"] || error48.response?.headers?.["x-amzn-requestid"];
49505
+ const method = error48.config?.method?.toUpperCase();
49506
+ const url3 = error48.config?.url;
49507
+ return new _KadoaHttpException(extra?.message || error48.message, {
49508
+ code: _KadoaHttpException.mapStatusToCode(error48),
49509
+ httpStatus: status,
49510
+ requestId,
49511
+ endpoint: url3,
49512
+ method,
49513
+ responseBody: error48.response?.data,
49514
+ details: extra?.details
49515
+ });
49516
+ }
49517
+ toJSON() {
49518
+ return {
49519
+ ...super.toJSON(),
49520
+ httpStatus: this.httpStatus,
49521
+ requestId: this.requestId,
49522
+ endpoint: this.endpoint,
49523
+ method: this.method,
49524
+ responseBody: this.responseBody
49525
+ };
49526
+ }
49527
+ toDetailedString() {
49528
+ const parts = [`${this.name}: ${this.message}`, `Code: ${this.code}`];
49529
+ if (this.httpStatus) {
49530
+ parts.push(`HTTP Status: ${this.httpStatus}`);
49531
+ }
49532
+ if (this.method && this.endpoint) {
49533
+ parts.push(`Request: ${this.method} ${this.endpoint}`);
49534
+ }
49535
+ if (this.requestId) {
49536
+ parts.push(`Request ID: ${this.requestId}`);
49537
+ }
49538
+ if (this.responseBody) {
49539
+ parts.push(`Response Body: ${JSON.stringify(this.responseBody, null, 2)}`);
49540
+ }
49541
+ if (this.details && Object.keys(this.details).length > 0) {
49542
+ parts.push(`Details: ${JSON.stringify(this.details, null, 2)}`);
49543
+ }
49544
+ if (this.cause) {
49545
+ parts.push(`Cause: ${this.cause}`);
49546
+ }
49547
+ return parts.join(`
49548
+ `);
49549
+ }
49550
+ static wrap(error48, extra) {
49551
+ if (error48 instanceof _KadoaHttpException)
49552
+ return error48;
49553
+ if (error48 instanceof KadoaSdkException)
49554
+ return error48;
49555
+ if (isAxiosError2(error48)) {
49556
+ return _KadoaHttpException.fromAxiosError(error48, extra);
49557
+ }
49558
+ return KadoaSdkException.wrap(error48, extra);
49559
+ }
49560
+ static mapStatusToCode(errorOrStatus) {
49561
+ const status = typeof errorOrStatus === "number" ? errorOrStatus : errorOrStatus.response?.status;
49562
+ if (!status) {
49563
+ if (typeof errorOrStatus === "number")
49564
+ return "UNKNOWN";
49565
+ return errorOrStatus.code === "ECONNABORTED" ? "TIMEOUT" : errorOrStatus.request ? "NETWORK_ERROR" : "UNKNOWN";
49566
+ }
49567
+ if (status === 401 || status === 403)
49568
+ return "AUTH_ERROR";
49569
+ if (status === 404)
49570
+ return "NOT_FOUND";
49571
+ if (status === 408)
49572
+ return "TIMEOUT";
49573
+ if (status === 429)
49574
+ return "RATE_LIMITED";
49575
+ if (status >= 400 && status < 500)
49576
+ return "VALIDATION_ERROR";
49577
+ if (status >= 500)
49578
+ return "HTTP_ERROR";
49579
+ return "UNKNOWN";
49580
+ }
49581
+ };
49582
+ logger = {
49583
+ changes: createLogger("changes"),
49584
+ client: createLogger("client"),
49585
+ wss: createLogger("wss"),
49586
+ extraction: createLogger("extraction"),
49587
+ http: createLogger("http"),
49588
+ workflow: createLogger("workflow"),
49589
+ crawl: createLogger("crawl"),
49590
+ notifications: createLogger("notifications"),
49591
+ schemas: createLogger("schemas"),
49592
+ validation: createLogger("validation"),
49593
+ templates: createLogger("templates"),
49594
+ variables: createLogger("variables")
49595
+ };
49596
+ debug = logger.changes;
49597
+ BASE_PATH = "https://api.kadoa.com".replace(/\/+$/, "");
49598
+ RequiredError = class extends Error {
49599
+ constructor(field, msg) {
49600
+ super(msg);
49601
+ this.field = field;
49602
+ this.name = "RequiredError";
49603
+ }
49604
+ };
49605
+ operationServerMap = {};
49606
+ CrawlerApi = class extends BaseAPI {
49607
+ v4CrawlBucketDataFilenameb64Get(requestParameters, options) {
49608
+ return CrawlerApiFp(this.configuration).v4CrawlBucketDataFilenameb64Get(requestParameters.filenameb64, requestParameters.contentType, requestParameters.cacheControl, options).then((request) => request(this.axios, this.basePath));
49609
+ }
49610
+ v4CrawlConfigConfigIdGet(requestParameters, options) {
49611
+ return CrawlerApiFp(this.configuration).v4CrawlConfigConfigIdGet(requestParameters.configId, options).then((request) => request(this.axios, this.basePath));
49612
+ }
49613
+ v4CrawlConfigDelete(requestParameters = {}, options) {
49614
+ return CrawlerApiFp(this.configuration).v4CrawlConfigDelete(requestParameters.deleteCrawlerConfigRequest, options).then((request) => request(this.axios, this.basePath));
49615
+ }
49616
+ v4CrawlConfigPost(requestParameters = {}, options) {
49617
+ return CrawlerApiFp(this.configuration).v4CrawlConfigPost(requestParameters.createCrawlerConfigRequest, options).then((request) => request(this.axios, this.basePath));
49618
+ }
49619
+ v4CrawlPausePost(requestParameters = {}, options) {
49620
+ return CrawlerApiFp(this.configuration).v4CrawlPausePost(requestParameters.pauseCrawlerSessionRequest, options).then((request) => request(this.axios, this.basePath));
49621
+ }
49622
+ v4CrawlPost(requestParameters = {}, options) {
49623
+ return CrawlerApiFp(this.configuration).v4CrawlPost(requestParameters.startCrawlerSessionRequest, options).then((request) => request(this.axios, this.basePath));
49624
+ }
49625
+ v4CrawlResumePost(requestParameters = {}, options) {
49626
+ return CrawlerApiFp(this.configuration).v4CrawlResumePost(requestParameters.resumeCrawlerSessionRequest, options).then((request) => request(this.axios, this.basePath));
49627
+ }
49628
+ v4CrawlSessionIdListGet(requestParameters, options) {
49629
+ return CrawlerApiFp(this.configuration).v4CrawlSessionIdListGet(requestParameters.sessionId, requestParameters.includeAll, options).then((request) => request(this.axios, this.basePath));
49630
+ }
49631
+ v4CrawlSessionIdPagesGet(requestParameters, options) {
49632
+ return CrawlerApiFp(this.configuration).v4CrawlSessionIdPagesGet(requestParameters.sessionId, requestParameters.currentPage, requestParameters.pageSize, options).then((request) => request(this.axios, this.basePath));
49633
+ }
49634
+ v4CrawlSessionIdPagesPageIdGet(requestParameters, options) {
49635
+ return CrawlerApiFp(this.configuration).v4CrawlSessionIdPagesPageIdGet(requestParameters.sessionId, requestParameters.pageId, requestParameters.format, options).then((request) => request(this.axios, this.basePath));
49636
+ }
49637
+ v4CrawlSessionIdStatusGet(requestParameters, options) {
49638
+ return CrawlerApiFp(this.configuration).v4CrawlSessionIdStatusGet(requestParameters.sessionId, options).then((request) => request(this.axios, this.basePath));
49639
+ }
49640
+ v4CrawlSessionsGet(requestParameters = {}, options) {
49641
+ return CrawlerApiFp(this.configuration).v4CrawlSessionsGet(requestParameters.page, requestParameters.pageSize, requestParameters.userId, options).then((request) => request(this.axios, this.basePath));
49642
+ }
49643
+ v4CrawlStartPost(requestParameters = {}, options) {
49644
+ return CrawlerApiFp(this.configuration).v4CrawlStartPost(requestParameters.startSessionWithConfigRequest, options).then((request) => request(this.axios, this.basePath));
49645
+ }
49646
+ };
49647
+ DataValidationApi = class extends BaseAPI {
49648
+ v4DataValidationRulesActionsBulkApprovePost(requestParameters = {}, options) {
49649
+ return DataValidationApiFp(this.configuration).v4DataValidationRulesActionsBulkApprovePost(requestParameters.bulkApproveRules, options).then((request) => request(this.axios, this.basePath));
49650
+ }
49651
+ v4DataValidationRulesActionsBulkDeletePost(requestParameters = {}, options) {
49652
+ return DataValidationApiFp(this.configuration).v4DataValidationRulesActionsBulkDeletePost(requestParameters.bulkDeleteRules, options).then((request) => request(this.axios, this.basePath));
49653
+ }
49654
+ v4DataValidationRulesActionsDeleteAllDelete(requestParameters = {}, options) {
49655
+ return DataValidationApiFp(this.configuration).v4DataValidationRulesActionsDeleteAllDelete(requestParameters.deleteRuleWithReason, options).then((request) => request(this.axios, this.basePath));
49656
+ }
49657
+ v4DataValidationRulesActionsGeneratePost(requestParameters = {}, options) {
49658
+ return DataValidationApiFp(this.configuration).v4DataValidationRulesActionsGeneratePost(requestParameters.generateRule, options).then((request) => request(this.axios, this.basePath));
49659
+ }
49366
49660
  v4DataValidationRulesActionsGenerateRulesPost(requestParameters = {}, options) {
49367
49661
  return DataValidationApiFp(this.configuration).v4DataValidationRulesActionsGenerateRulesPost(requestParameters.generateRules, options).then((request) => request(this.axios, this.basePath));
49368
49662
  }
@@ -49636,215 +49930,25 @@ var init_dist2 = __esm(() => {
49636
49930
  Text: DataFieldDataTypeEnum.String,
49637
49931
  Url: DataFieldDataTypeEnum.Link
49638
49932
  };
49639
- KadoaErrorCode = {
49640
- VALIDATION_ERROR: "VALIDATION_ERROR",
49641
- BAD_REQUEST: "BAD_REQUEST",
49642
- NOT_FOUND: "NOT_FOUND",
49643
- INTERNAL_ERROR: "INTERNAL_ERROR"
49644
- };
49645
- _KadoaSdkException = class _KadoaSdkException2 extends Error {
49646
- constructor(message, options) {
49647
- super(message);
49648
- this.name = "KadoaSdkException";
49649
- this.code = options?.code ?? "UNKNOWN";
49650
- this.details = options?.details;
49651
- if (options && "cause" in options)
49652
- this.cause = options.cause;
49653
- Error.captureStackTrace?.(this, _KadoaSdkException2);
49654
- }
49655
- static from(error48, details) {
49656
- if (error48 instanceof _KadoaSdkException2)
49657
- return error48;
49658
- const message = error48 instanceof Error ? error48.message : typeof error48 === "string" ? error48 : "Unexpected error";
49659
- return new _KadoaSdkException2(message, {
49660
- code: "UNKNOWN",
49661
- details,
49662
- cause: error48
49663
- });
49664
- }
49665
- toJSON() {
49666
- return {
49667
- name: this.name,
49668
- message: this.message,
49669
- code: this.code,
49670
- details: this.details
49671
- };
49672
- }
49673
- toString() {
49674
- return [this.name, this.code, this.message].filter(Boolean).join(": ");
49675
- }
49676
- toDetailedString() {
49677
- const parts = [`${this.name}: ${this.message}`, `Code: ${this.code}`];
49678
- if (this.details && Object.keys(this.details).length > 0) {
49679
- parts.push(`Details: ${JSON.stringify(this.details, null, 2)}`);
49680
- }
49681
- if (this.cause) {
49682
- parts.push(`Cause: ${this.cause}`);
49683
- }
49684
- return parts.join(`
49685
- `);
49686
- }
49687
- static isInstance(error48) {
49688
- return error48 instanceof _KadoaSdkException2;
49689
- }
49690
- static wrap(error48, extra) {
49691
- if (error48 instanceof _KadoaSdkException2)
49692
- return error48;
49693
- const message = extra?.message || (error48 instanceof Error ? error48.message : typeof error48 === "string" ? error48 : "Unexpected error");
49694
- return new _KadoaSdkException2(message, {
49695
- code: "UNKNOWN",
49696
- details: extra?.details,
49697
- cause: error48
49698
- });
49699
- }
49700
- };
49701
- _KadoaSdkException.ERROR_MESSAGES = {
49702
- CONFIG_ERROR: "Invalid configuration provided",
49703
- AUTH_FAILED: "Authentication failed. Please check your API key",
49704
- RATE_LIMITED: "Rate limit exceeded. Please try again later",
49705
- NETWORK_ERROR: "Network error occurred",
49706
- SERVER_ERROR: "Server error occurred",
49707
- PARSE_ERROR: "Failed to parse response",
49708
- BAD_REQUEST: "Bad request",
49709
- ABORTED: "Aborted",
49710
- NOT_FOUND: "Not found",
49711
- NO_WORKFLOW_ID: "Failed to start extraction process - no ID received",
49712
- WORKFLOW_CREATE_FAILED: "Failed to create workflow",
49713
- WORKFLOW_TIMEOUT: "Workflow processing timed out",
49714
- WORKFLOW_UNEXPECTED_STATUS: "Extraction completed with unexpected status",
49715
- PROGRESS_CHECK_FAILED: "Failed to check extraction progress",
49716
- DATA_FETCH_FAILED: "Failed to retrieve extracted data from workflow",
49717
- NO_URLS: "At least one URL is required for extraction",
49718
- NO_API_KEY: "API key is required for entity detection",
49719
- LINK_REQUIRED: "Link is required for entity field detection",
49720
- NO_PREDICTIONS: "No entity predictions returned from the API",
49721
- EXTRACTION_FAILED: "Data extraction failed for the provided URLs",
49722
- ENTITY_FETCH_FAILED: "Failed to fetch entity fields",
49723
- ENTITY_INVARIANT_VIOLATION: "No valid entity provided",
49724
- SCHEMA_NOT_FOUND: "Schema not found",
49725
- SCHEMA_FETCH_ERROR: "Failed to fetch schema",
49726
- SCHEMAS_FETCH_ERROR: "Failed to fetch schemas",
49727
- SCHEMA_CREATE_FAILED: "Failed to create schema",
49728
- SCHEMA_UPDATE_FAILED: "Failed to update schema",
49729
- SCHEMA_DELETE_FAILED: "Failed to delete schema",
49730
- VARIABLE_NOT_FOUND: "Variable not found",
49731
- VARIABLE_CREATE_FAILED: "Failed to create variable",
49732
- VARIABLE_UPDATE_FAILED: "Failed to update variable",
49733
- TEMPLATE_NOT_FOUND: "Template not found",
49734
- TEMPLATE_CREATE_FAILED: "Failed to create template",
49735
- TEMPLATE_UPDATE_FAILED: "Failed to update template",
49736
- TEMPLATE_VERSION_CREATE_FAILED: "Failed to create template version",
49737
- TEMPLATE_FROM_WORKFLOW_FAILED: "Failed to create template from workflow"
49738
- };
49739
- KadoaSdkException = _KadoaSdkException;
49740
- ERROR_MESSAGES = KadoaSdkException.ERROR_MESSAGES;
49741
- KadoaHttpException = class _KadoaHttpException extends KadoaSdkException {
49742
- constructor(message, options) {
49743
- super(message, {
49744
- code: options?.code,
49745
- details: options?.details,
49746
- cause: options?.cause
49747
- });
49748
- this.name = "KadoaHttpException";
49749
- this.httpStatus = options?.httpStatus;
49750
- this.requestId = options?.requestId;
49751
- this.endpoint = options?.endpoint;
49752
- this.method = options?.method;
49753
- this.responseBody = options?.responseBody;
49754
- }
49755
- static fromAxiosError(error48, extra) {
49756
- const status = error48.response?.status;
49757
- const requestId = error48.response?.headers?.["x-request-id"] || error48.response?.headers?.["x-amzn-requestid"];
49758
- const method = error48.config?.method?.toUpperCase();
49759
- const url3 = error48.config?.url;
49760
- return new _KadoaHttpException(extra?.message || error48.message, {
49761
- code: _KadoaHttpException.mapStatusToCode(error48),
49762
- httpStatus: status,
49763
- requestId,
49764
- endpoint: url3,
49765
- method,
49766
- responseBody: error48.response?.data,
49767
- details: extra?.details
49768
- });
49769
- }
49770
- toJSON() {
49771
- return {
49772
- ...super.toJSON(),
49773
- httpStatus: this.httpStatus,
49774
- requestId: this.requestId,
49775
- endpoint: this.endpoint,
49776
- method: this.method,
49777
- responseBody: this.responseBody
49778
- };
49779
- }
49780
- toDetailedString() {
49781
- const parts = [`${this.name}: ${this.message}`, `Code: ${this.code}`];
49782
- if (this.httpStatus) {
49783
- parts.push(`HTTP Status: ${this.httpStatus}`);
49784
- }
49785
- if (this.method && this.endpoint) {
49786
- parts.push(`Request: ${this.method} ${this.endpoint}`);
49787
- }
49788
- if (this.requestId) {
49789
- parts.push(`Request ID: ${this.requestId}`);
49790
- }
49791
- if (this.responseBody) {
49792
- parts.push(`Response Body: ${JSON.stringify(this.responseBody, null, 2)}`);
49793
- }
49794
- if (this.details && Object.keys(this.details).length > 0) {
49795
- parts.push(`Details: ${JSON.stringify(this.details, null, 2)}`);
49796
- }
49797
- if (this.cause) {
49798
- parts.push(`Cause: ${this.cause}`);
49799
- }
49800
- return parts.join(`
49801
- `);
49802
- }
49803
- static wrap(error48, extra) {
49804
- if (error48 instanceof _KadoaHttpException)
49805
- return error48;
49806
- if (error48 instanceof KadoaSdkException)
49807
- return error48;
49808
- if (isAxiosError2(error48)) {
49809
- return _KadoaHttpException.fromAxiosError(error48, extra);
49810
- }
49811
- return KadoaSdkException.wrap(error48, extra);
49812
- }
49813
- static mapStatusToCode(errorOrStatus) {
49814
- const status = typeof errorOrStatus === "number" ? errorOrStatus : errorOrStatus.response?.status;
49815
- if (!status) {
49816
- if (typeof errorOrStatus === "number")
49817
- return "UNKNOWN";
49818
- return errorOrStatus.code === "ECONNABORTED" ? "TIMEOUT" : errorOrStatus.request ? "NETWORK_ERROR" : "UNKNOWN";
49819
- }
49820
- if (status === 401 || status === 403)
49821
- return "AUTH_ERROR";
49822
- if (status === 404)
49823
- return "NOT_FOUND";
49824
- if (status === 408)
49825
- return "TIMEOUT";
49826
- if (status === 429)
49827
- return "RATE_LIMITED";
49828
- if (status >= 400 && status < 500)
49829
- return "VALIDATION_ERROR";
49830
- if (status >= 500)
49831
- return "HTTP_ERROR";
49832
- return "UNKNOWN";
49933
+ RAW_HELPER_FIELD_CONFIG = {
49934
+ HTML: {
49935
+ dataType: "STRING",
49936
+ description: "Full page HTML as a string. Return the raw HTML content.",
49937
+ example: "<html><body><h1>Example page</h1></body></html>"
49938
+ },
49939
+ MARKDOWN: {
49940
+ dataType: "STRING",
49941
+ description: "Main page content rendered as markdown. Return the markdown as a string.",
49942
+ example: `# Example page
49943
+
49944
+ This is the main page content.`
49945
+ },
49946
+ PAGE_URL: {
49947
+ dataType: "LINK",
49948
+ description: "Canonical page URL for the extracted page. Return the resolved page URL.",
49949
+ example: "https://example.com/page"
49833
49950
  }
49834
49951
  };
49835
- logger = {
49836
- client: createLogger("client"),
49837
- wss: createLogger("wss"),
49838
- extraction: createLogger("extraction"),
49839
- http: createLogger("http"),
49840
- workflow: createLogger("workflow"),
49841
- crawl: createLogger("crawl"),
49842
- notifications: createLogger("notifications"),
49843
- schemas: createLogger("schemas"),
49844
- validation: createLogger("validation"),
49845
- templates: createLogger("templates"),
49846
- variables: createLogger("variables")
49847
- };
49848
49952
  _SchemaBuilder.FIELD_NAME_PATTERN = /^[A-Za-z0-9]+$/;
49849
49953
  _SchemaBuilder.TYPES_REQUIRING_EXAMPLE = [
49850
49954
  "STRING",
@@ -49854,19 +49958,26 @@ var init_dist2 = __esm(() => {
49854
49958
  "ARRAY"
49855
49959
  ];
49856
49960
  SchemaBuilder = _SchemaBuilder;
49857
- debug = logger.schemas;
49858
- debug2 = logger.extraction;
49961
+ debug2 = logger.schemas;
49962
+ debug3 = logger.extraction;
49859
49963
  SUCCESSFUL_RUN_STATES = /* @__PURE__ */ new Set(["FINISHED", "SUCCESS"]);
49860
49964
  DEFAULT_OPTIONS = {
49861
49965
  mode: "run",
49862
49966
  pollingInterval: 5000,
49863
49967
  maxWaitTime: 300000,
49864
- navigationMode: "single-page",
49865
49968
  location: { type: "auto" },
49866
49969
  bypassPreview: true,
49867
49970
  autoStart: true
49868
49971
  };
49869
- debug3 = logger.extraction;
49972
+ debug4 = logger.extraction;
49973
+ TERMINAL_RUN_STATES = /* @__PURE__ */ new Set([
49974
+ "FINISHED",
49975
+ "SUCCESS",
49976
+ "FAILED",
49977
+ "ERROR",
49978
+ "STOPPED",
49979
+ "CANCELLED"
49980
+ ]);
49870
49981
  NotificationChannelType = {
49871
49982
  EMAIL: "EMAIL",
49872
49983
  SLACK: "SLACK",
@@ -49876,19 +49987,19 @@ var init_dist2 = __esm(() => {
49876
49987
  EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
49877
49988
  _NotificationChannelsService.DEFAULT_CHANNEL_NAME = "default";
49878
49989
  NotificationChannelsService = _NotificationChannelsService;
49879
- debug4 = logger.notifications;
49990
+ debug5 = logger.notifications;
49880
49991
  PUBLIC_API_URI = process.env.KADOA_PUBLIC_API_URI ?? "https://api.kadoa.com";
49881
49992
  WSS_API_URI = process.env.KADOA_WSS_API_URI ?? "wss://realtime.kadoa.com";
49882
49993
  process.env.KADOA_WSS_NEO_API_URI;
49883
49994
  REALTIME_API_URI = process.env.KADOA_REALTIME_API_URI ?? "https://realtime.kadoa.com";
49884
- debug5 = logger.wss;
49995
+ debug6 = logger.wss;
49885
49996
  if (typeof WebSocket === "undefined") {
49886
49997
  global.WebSocket = __require2("ws");
49887
49998
  }
49888
49999
  _Realtime.DEFAULT_RECONNECT_DELAY_MS = 5000;
49889
50000
  _Realtime.MAX_RECONNECT_DELAY_MS = 60000;
49890
50001
  Realtime = _Realtime;
49891
- debug6 = logger.templates;
50002
+ debug7 = logger.templates;
49892
50003
  DEFAULT_POLLING_OPTIONS = {
49893
50004
  pollIntervalMs: 1e4,
49894
50005
  timeoutMs: 5 * 60 * 1000
@@ -49897,7 +50008,7 @@ var init_dist2 = __esm(() => {
49897
50008
  ABORTED: "ABORTED",
49898
50009
  TIMEOUT: "TIMEOUT"
49899
50010
  };
49900
- debug7 = logger.variables;
50011
+ debug8 = logger.variables;
49901
50012
  JobStateEnum = {
49902
50013
  Finished: "FINISHED",
49903
50014
  Failed: "FAILED",
@@ -49910,7 +50021,7 @@ var init_dist2 = __esm(() => {
49910
50021
  JobStateEnum.NotSupported,
49911
50022
  JobStateEnum.FailedInsufficientFunds
49912
50023
  ]);
49913
- TERMINAL_RUN_STATES = /* @__PURE__ */ new Set([
50024
+ TERMINAL_RUN_STATES2 = /* @__PURE__ */ new Set([
49914
50025
  "FINISHED",
49915
50026
  "SUCCESS",
49916
50027
  "FAILED",
@@ -49918,7 +50029,7 @@ var init_dist2 = __esm(() => {
49918
50029
  "STOPPED",
49919
50030
  "CANCELLED"
49920
50031
  ]);
49921
- debug8 = logger.workflow;
50032
+ debug9 = logger.workflow;
49922
50033
  });
49923
50034
 
49924
50035
  // src/client.ts
@@ -50115,6 +50226,9 @@ function coerceBoolean() {
50115
50226
  return val;
50116
50227
  };
50117
50228
  }
50229
+ function coerceNull() {
50230
+ return (val) => val === "null" ? undefined : val;
50231
+ }
50118
50232
  function coerceJson() {
50119
50233
  return (val) => {
50120
50234
  if (typeof val === "string") {
@@ -50146,17 +50260,33 @@ function extractApiMessage(responseBody) {
50146
50260
  const body = responseBody;
50147
50261
  if (!body || typeof body !== "object")
50148
50262
  return;
50149
- const msg = typeof body.error === "string" && body.error || typeof body.message === "string" && body.message || undefined;
50150
- if (!msg)
50151
- return;
50263
+ let msg = typeof body.error === "string" && body.error || typeof body.message === "string" && body.message || undefined;
50152
50264
  if (body.validationErrors && typeof body.validationErrors === "object" && body.validationErrors !== null) {
50153
50265
  const details = Object.entries(body.validationErrors).map(([field, err]) => `${field}: "${err}"`).join(", ");
50154
- if (details)
50155
- return `${msg} — Details: ${details}`;
50266
+ if (details) {
50267
+ msg = msg ? `${msg} — Details: ${details}` : `Validation failed — Details: ${details}`;
50268
+ }
50156
50269
  }
50157
50270
  return msg;
50158
50271
  }
50159
- function classifyError(error48) {
50272
+ function inferResourceType(toolName) {
50273
+ if (!toolName)
50274
+ return "resource";
50275
+ if (toolName.includes("template") || toolName.includes("version"))
50276
+ return "template";
50277
+ if (toolName.includes("variable"))
50278
+ return "variable";
50279
+ if (toolName.includes("workflow") || toolName.includes("monitor"))
50280
+ return "workflow";
50281
+ if (toolName.includes("channel") || toolName.includes("notification"))
50282
+ return "notification channel";
50283
+ if (toolName.includes("schema"))
50284
+ return "schema";
50285
+ if (toolName.includes("change"))
50286
+ return "change record";
50287
+ return "resource";
50288
+ }
50289
+ function classifyError(error48, toolName) {
50160
50290
  if (KadoaSdkException.isInstance(error48)) {
50161
50291
  const code = error48.code;
50162
50292
  if (KadoaHttpException.isInstance(error48)) {
@@ -50168,8 +50298,10 @@ function classifyError(error48) {
50168
50298
  return `Access denied${status}. Your current team role may not have permission for this action. Use the whoami tool to check your role, or contact your team admin to request elevated access.`;
50169
50299
  }
50170
50300
  return `Authentication failed${status}. Please re-authenticate via OAuth.`;
50171
- case "NOT_FOUND":
50172
- return `Not found${status}. The workflow may have been deleted or the ID is incorrect.`;
50301
+ case "NOT_FOUND": {
50302
+ const resource = inferResourceType(toolName);
50303
+ return `Not found${status}. The ${resource} may have been deleted or the ID is incorrect.`;
50304
+ }
50173
50305
  case "RATE_LIMITED":
50174
50306
  return `Rate limit exceeded${status}. Please wait a moment and try again.`;
50175
50307
  case "NETWORK_ERROR":
@@ -50186,8 +50318,10 @@ function classifyError(error48) {
50186
50318
  switch (code) {
50187
50319
  case "AUTH_ERROR":
50188
50320
  return "Authentication failed. Please re-authenticate via OAuth.";
50189
- case "NOT_FOUND":
50190
- return "Not found. The workflow may have been deleted or the ID is incorrect.";
50321
+ case "NOT_FOUND": {
50322
+ const resource = inferResourceType(toolName);
50323
+ return `Not found. The ${resource} may have been deleted or the ID is incorrect.`;
50324
+ }
50191
50325
  case "RATE_LIMITED":
50192
50326
  return "Rate limit exceeded. Please wait a moment and try again.";
50193
50327
  case "NETWORK_ERROR":
@@ -50230,7 +50364,7 @@ function registerTools(server, ctx) {
50230
50364
  console.error(`[Tool Error] ${name}: session expired, user must re-authenticate`);
50231
50365
  return errorResult("Your session has expired. Please reconnect the MCP server to re-authenticate.");
50232
50366
  }
50233
- let message = classifyError(error48);
50367
+ let message = classifyError(error48, name);
50234
50368
  if (KadoaHttpException.isInstance(error48) && error48.httpStatus === 403) {
50235
50369
  try {
50236
50370
  const jwt2 = ctx.supabaseJwt;
@@ -50418,7 +50552,6 @@ function registerTools(server, ctx) {
50418
50552
  let builder = ctx.client.extract({
50419
50553
  urls,
50420
50554
  name: args.name || "Untitled Workflow",
50421
- navigationMode: "agentic-navigation",
50422
50555
  userPrompt: args.prompt,
50423
50556
  extraction: buildExtraction(args),
50424
50557
  interval: args.updateInterval,
@@ -50608,6 +50741,56 @@ function registerTools(server, ctx) {
50608
50741
  total: data.pagination?.totalCount || data.data.length
50609
50742
  });
50610
50743
  }));
50744
+ server.registerTool("list_changes", {
50745
+ description: "List detected data changes across one or more real-time monitoring workflows. " + "Returns structured diffs showing added, removed, and changed records. " + "Only works for workflows with real-time monitoring enabled.",
50746
+ inputSchema: {
50747
+ workflowIds: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string())).optional().describe("Workflow IDs to filter by. If omitted, returns changes for all ACTIVE monitoring workflows."),
50748
+ startDate: exports_external.string().optional().describe("Start date filter (ISO format, e.g. 2025-01-01)"),
50749
+ endDate: exports_external.string().optional().describe("End date filter (ISO format, e.g. 2025-12-31)"),
50750
+ skip: exports_external.preprocess(coerceNumber(), exports_external.number()).optional().describe("Number of records to skip for pagination"),
50751
+ limit: exports_external.preprocess(coerceNumber(), exports_external.number()).optional().describe("Maximum number of changes to return")
50752
+ },
50753
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true }
50754
+ }, withErrorHandling("list_changes", async (args) => {
50755
+ const result = await ctx.client.changes.list({
50756
+ workflowIds: args.workflowIds?.join(","),
50757
+ startDate: args.startDate,
50758
+ endDate: args.endDate,
50759
+ skip: args.skip,
50760
+ limit: args.limit ?? 25
50761
+ });
50762
+ return jsonResult({
50763
+ changes: result.changes.map((c) => ({
50764
+ id: c.id,
50765
+ workflowId: c.workflowId,
50766
+ url: c.url,
50767
+ summary: c.summary,
50768
+ differences: c.differences,
50769
+ createdAt: c.createdAt
50770
+ })),
50771
+ pagination: result.pagination,
50772
+ changesCount: result.changesCount
50773
+ });
50774
+ }));
50775
+ server.registerTool("get_change", {
50776
+ description: "Get detailed information about a specific detected change, including the full data snapshot and diff.",
50777
+ inputSchema: {
50778
+ changeId: exports_external.string().describe("The change ID")
50779
+ },
50780
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true }
50781
+ }, withErrorHandling("get_change", async (args) => {
50782
+ const change = await ctx.client.changes.get(args.changeId);
50783
+ return jsonResult({
50784
+ id: change.id,
50785
+ workflowId: change.workflowId,
50786
+ url: change.url,
50787
+ summary: change.summary,
50788
+ screenshotUrl: change.screenshotUrl,
50789
+ data: change.data,
50790
+ differences: change.differences,
50791
+ createdAt: change.createdAt
50792
+ });
50793
+ }));
50611
50794
  server.registerTool("delete_workflow", {
50612
50795
  description: "Delete a workflow permanently. This is irreversible. " + "You MUST first call this tool without confirmed=true to preview what will be deleted, " + "then show the user the workflow name and ask for confirmation, " + "then call again with confirmed=true only after the user explicitly agrees.",
50613
50796
  inputSchema: {
@@ -51083,7 +51266,7 @@ function registerTools(server, ctx) {
51083
51266
  });
51084
51267
  }));
51085
51268
  server.registerTool("list_templates", {
51086
- description: "List all templates in the current team. Templates define reusable configurations (prompt, schema, notifications) that can be linked to multiple workflows.",
51269
+ description: "List all templates in the current team. Templates define reusable configurations (prompt, schema, notifications).",
51087
51270
  inputSchema: strictSchema({}),
51088
51271
  annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true }
51089
51272
  }, withErrorHandling("list_templates", async () => {
@@ -51101,7 +51284,7 @@ function registerTools(server, ctx) {
51101
51284
  return jsonResult({ template });
51102
51285
  }));
51103
51286
  server.registerTool("create_template", {
51104
- description: "Create a new template. Templates define reusable configurations that can be linked to workflows. After creation, use create_template_version to publish a version with prompt, schema, and notifications.",
51287
+ description: "Create a new template. After creation, use create_template_version to publish a version with prompt, schema, and notifications.",
51105
51288
  inputSchema: strictSchema({
51106
51289
  name: exports_external.string().describe("Template name (1-255 chars)"),
51107
51290
  description: exports_external.string().optional().describe("Template description (max 2000 chars)")
@@ -51122,8 +51305,8 @@ function registerTools(server, ctx) {
51122
51305
  description: "Update a template's name or description. At least one field must be provided.",
51123
51306
  inputSchema: strictSchema({
51124
51307
  templateId: exports_external.string().describe("The template ID to update"),
51125
- name: exports_external.string().optional().describe("New template name"),
51126
- description: exports_external.string().optional().describe("New template description")
51308
+ name: exports_external.preprocess(coerceNull(), exports_external.string().optional()).describe("New template name"),
51309
+ description: exports_external.preprocess(coerceNull(), exports_external.string().optional()).describe("New template description")
51127
51310
  }),
51128
51311
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true }
51129
51312
  }, withErrorHandling("update_template", async (args) => {
@@ -51136,7 +51319,7 @@ function registerTools(server, ctx) {
51136
51319
  });
51137
51320
  }));
51138
51321
  server.registerTool("delete_template", {
51139
- description: "Delete (archive) a template. Existing linked workflows keep their current config but are unlinked. " + "You MUST first call this tool without confirmed=true to preview what will be deleted, " + "then show the user the template name and ask for confirmation, " + "then call again with confirmed=true only after the user explicitly agrees.",
51322
+ description: "Delete (archive) a template. " + "You MUST first call this tool without confirmed=true to preview what will be deleted, " + "then show the user the template name and ask for confirmation, " + "then call again with confirmed=true only after the user explicitly agrees.",
51140
51323
  inputSchema: strictSchema({
51141
51324
  templateId: exports_external.string().describe("The template ID to delete"),
51142
51325
  confirmed: exports_external.preprocess(coerceBoolean(), exports_external.boolean()).optional().describe("Set to true only after the user has explicitly confirmed deletion. Omit or set to false for the initial preview call.")
@@ -51153,7 +51336,7 @@ function registerTools(server, ctx) {
51153
51336
  pending: true,
51154
51337
  templateId: args.templateId,
51155
51338
  templateName,
51156
- message: `⚠️ You are about to delete template "${templateName}". Linked workflows will keep their current config but will be unlinked. Ask the user to confirm, then call delete_template again with confirmed=true.`
51339
+ message: `⚠️ You are about to delete template "${templateName}". Ask the user to confirm, then call delete_template again with confirmed=true.`
51157
51340
  });
51158
51341
  }
51159
51342
  await ctx.client.template.delete(args.templateId);
@@ -51196,98 +51379,14 @@ function registerTools(server, ctx) {
51196
51379
  message: `Version ${version2.version} published for template ${templateId}.`
51197
51380
  });
51198
51381
  }));
51199
- server.registerTool("list_template_workflows", {
51200
- description: "List all workflows linked to a template.",
51201
- inputSchema: strictSchema({
51202
- templateId: exports_external.string().describe("The template ID")
51203
- }),
51204
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true }
51205
- }, withErrorHandling("list_template_workflows", async (args) => {
51206
- const workflows = await ctx.client.template.listWorkflows(args.templateId);
51207
- return jsonResult({ workflows, count: workflows.length });
51208
- }));
51209
- server.registerTool("link_workflows_to_template", {
51210
- description: "Link workflows to a template. Linking applies the template's latest version config to the workflows. " + "Without force, fails if any workflow is already linked to a different template. With force=true, relinks them. " + "You MUST first call without confirmed=true to preview, then ask the user for confirmation, " + "then call again with confirmed=true.",
51211
- inputSchema: strictSchema({
51212
- templateId: exports_external.string().describe("The template ID to link workflows to"),
51213
- workflowIds: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.string())).describe("Array of workflow IDs to link"),
51214
- force: exports_external.preprocess(coerceBoolean(), exports_external.boolean()).optional().describe("If true, relink workflows already linked to another template"),
51215
- confirmed: exports_external.preprocess(coerceBoolean(), exports_external.boolean()).optional().describe("Set to true only after user confirms. Omit for preview.")
51216
- }),
51217
- annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false }
51218
- }, withErrorHandling("link_workflows_to_template", async (args) => {
51219
- if (!args.confirmed) {
51220
- const forceNote = args.force ? " Workflows already linked to other templates will be relinked (force=true)." : " Will fail if any workflow is already linked to a different template.";
51221
- return jsonResult({
51222
- pending: true,
51223
- templateId: args.templateId,
51224
- workflowIds: args.workflowIds,
51225
- force: !!args.force,
51226
- message: `⚠️ You are about to link ${args.workflowIds.length} workflow(s) to template ${args.templateId}. This will apply the template's latest version config to these workflows.${forceNote} Ask the user to confirm, then call again with confirmed=true.`
51227
- });
51228
- }
51229
- const result = await ctx.client.template.linkWorkflows(args.templateId, {
51230
- workflowIds: args.workflowIds,
51231
- ...args.force != null && { force: args.force }
51232
- });
51233
- return jsonResult({
51234
- success: true,
51235
- result,
51236
- message: `Linked ${args.workflowIds.length} workflow(s) to template ${args.templateId}.`
51237
- });
51238
- }));
51239
- server.registerTool("unlink_workflows_from_template", {
51240
- description: "Unlink workflows from a template. Workflows keep their current config but are no longer associated with the template. " + "You MUST first call without confirmed=true to preview, then ask the user for confirmation, " + "then call again with confirmed=true.",
51241
- inputSchema: strictSchema({
51242
- templateId: exports_external.string().describe("The template ID to unlink workflows from"),
51243
- workflowIds: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.string())).describe("Array of workflow IDs to unlink"),
51244
- confirmed: exports_external.preprocess(coerceBoolean(), exports_external.boolean()).optional().describe("Set to true only after user confirms. Omit for preview.")
51245
- }),
51246
- annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false }
51247
- }, withErrorHandling("unlink_workflows_from_template", async (args) => {
51248
- if (!args.confirmed) {
51249
- return jsonResult({
51250
- pending: true,
51251
- templateId: args.templateId,
51252
- workflowIds: args.workflowIds,
51253
- message: `⚠️ You are about to unlink ${args.workflowIds.length} workflow(s) from template ${args.templateId}. Workflows will keep their current config. Ask the user to confirm, then call again with confirmed=true.`
51254
- });
51255
- }
51256
- const result = await ctx.client.template.unlinkWorkflows(args.templateId, {
51257
- workflowIds: args.workflowIds
51258
- });
51259
- return jsonResult({
51260
- success: true,
51261
- result,
51262
- message: `Unlinked ${args.workflowIds.length} workflow(s) from template ${args.templateId}.`
51263
- });
51264
- }));
51265
- server.registerTool("apply_template_update", {
51266
- description: "Apply a specific template version to workflows. Updates the workflows' config (prompt, schema, notifications) to match the specified version.",
51267
- inputSchema: strictSchema({
51268
- templateId: exports_external.string().describe("The template ID"),
51269
- targetVersion: exports_external.preprocess(coerceNumber(), exports_external.number().int().min(1)).describe("Version number to apply"),
51270
- workflowIds: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.string())).describe("Array of workflow IDs to update (max 100)")
51271
- }),
51272
- annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false }
51273
- }, withErrorHandling("apply_template_update", async (args) => {
51274
- const result = await ctx.client.template.applyUpdate(args.templateId, {
51275
- targetVersion: args.targetVersion,
51276
- workflowIds: args.workflowIds
51277
- });
51278
- return jsonResult({
51279
- success: true,
51280
- result,
51281
- message: `Applied version ${args.targetVersion} to ${args.workflowIds.length} workflow(s).`
51282
- });
51283
- }));
51284
51382
  server.registerTool("save_workflow_as_template", {
51285
- description: "Create a template from an existing workflow's configuration (prompt, schema, notifications). " + "Provide 'name' to create a new template, or 'templateId' to add a new version to an existing template.",
51383
+ description: "Create a template from an existing workflow's configuration (prompt, schema, notifications). " + "Provide 'name' to create a new template, or 'templateId' to add a new version to an existing template. " + "Use 'includeParts' to save only specific parts of the configuration.",
51286
51384
  inputSchema: strictSchema({
51287
51385
  workflowId: exports_external.string().describe("Source workflow ID to extract config from"),
51288
51386
  name: exports_external.string().optional().describe("Name for the new template (required if templateId is not set)"),
51289
51387
  description: exports_external.string().optional().describe("Description for the new template"),
51290
- templateId: exports_external.string().optional().describe("Existing template ID to add a new version to (mutually exclusive with name)")
51388
+ templateId: exports_external.string().optional().describe("Existing template ID to add a new version to (mutually exclusive with name)"),
51389
+ includeParts: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.enum(["prompt", "schema", "notifications"])).optional()).describe("Which parts of the workflow config to include. Omit to include all. At least 1 required if provided.")
51291
51390
  }),
51292
51391
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false }
51293
51392
  }, withErrorHandling("save_workflow_as_template", async (args) => {
@@ -51295,7 +51394,8 @@ function registerTools(server, ctx) {
51295
51394
  workflowId: args.workflowId,
51296
51395
  ...args.name != null && { name: args.name },
51297
51396
  ...args.description != null && { description: args.description },
51298
- ...args.templateId != null && { templateId: args.templateId }
51397
+ ...args.templateId != null && { templateId: args.templateId },
51398
+ ...args.includeParts != null && { includeParts: args.includeParts }
51299
51399
  });
51300
51400
  return jsonResult({
51301
51401
  success: true,
@@ -51335,7 +51435,7 @@ var package_default;
51335
51435
  var init_package = __esm(() => {
51336
51436
  package_default = {
51337
51437
  name: "@kadoa/mcp",
51338
- version: "0.4.2",
51438
+ version: "0.4.3-rc.2",
51339
51439
  description: "Kadoa MCP Server — manage workflows from Claude Desktop, Cursor, and other MCP clients",
51340
51440
  type: "module",
51341
51441
  main: "dist/index.js",
@@ -51359,7 +51459,7 @@ var init_package = __esm(() => {
51359
51459
  prepublishOnly: "bun run check-types && bun run test:unit && bun run build"
51360
51460
  },
51361
51461
  dependencies: {
51362
- "@kadoa/node-sdk": "^0.26.0",
51462
+ "@kadoa/node-sdk": "^0.28.0",
51363
51463
  "@modelcontextprotocol/sdk": "^1.26.0",
51364
51464
  express: "^5.2.1",
51365
51465
  ioredis: "^5.6.1",
@@ -56586,6 +56686,7 @@ function createServer(auth) {
56586
56686
  "Workflow lifecycle: create_workflow \u2192 get_workflow (check status) \u2192 fetch_data (get results). Workflows run asynchronously \u2014 never poll or sleep-wait.",
56587
56687
  "",
56588
56688
  "Use create_realtime_monitor only when the user wants continuous change detection with alerts. For one-time or scheduled extraction, use create_workflow.",
56689
+ "Use list_changes and get_change to retrieve detected diffs from real-time monitoring workflows.",
56589
56690
  "",
56590
56691
  "Schema tips: Use descriptive field names and examples. Group related data under one entity.",
56591
56692
  "The AI agent uses the schema + prompt to understand what to extract \u2014 a detailed prompt with a comprehensive schema produces better results than multiple simple workflows."