@superglue/cli 1.1.14 → 1.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1925,7 +1925,9 @@ var require_types = __commonJS({
1925
1925
  RemoveScope2["ENTRY"] = "ENTRY";
1926
1926
  })(RemoveScope || (exports2.RemoveScope = RemoveScope = {}));
1927
1927
  function isRequestConfig(config) {
1928
- return config?.type === "request" || !config?.type;
1928
+ if (!config || typeof config !== "object")
1929
+ return false;
1930
+ return config.type === "request" || !("type" in config) || config.type === void 0;
1929
1931
  }
1930
1932
  function isTransformConfig(config) {
1931
1933
  return config?.type === "transform";
@@ -2389,7 +2391,7 @@ Use parameterized queries with $1, $2, etc. placeholders:
2389
2391
 
2390
2392
  <div style="margin-top: 24px; padding: 20px; background: #fefce8; border-radius: 12px; border: 1px solid #fef08a;">
2391
2393
  <p style="margin: 0; color: #854d0e; font-size: 14px;">
2392
- <strong>\u{1F4A1} This is a demo tool!</strong> You just ran your first superglue workflow.
2394
+ <strong>\u{1F4A1} This is a demo tool!</strong> You just ran your first superglue tool.
2393
2395
  Edit this tool or create your own to automate any API integration.
2394
2396
  </p>
2395
2397
  </div>
@@ -2415,6 +2417,7 @@ Use parameterized queries with $1, $2, etc. placeholders:
2415
2417
  }
2416
2418
  }
2417
2419
  },
2420
+ outputTransform: `(sourceData) => { const quote = sourceData.fetchStock?.data?.["Global Quote"] || {}; return { symbol: quote["01. symbol"] || sourceData.symbol || "AAPL", price: parseFloat(quote["05. price"] || "0").toFixed(2), change: quote["09. change"] || "0", changePercent: quote["10. change percent"] || "0%", volume: parseInt(quote["06. volume"] || "0").toLocaleString(), tradingDay: quote["07. latest trading day"] || "N/A", emailSent: sourceData.sendEmail?.success || false }; }`,
2418
2421
  instruction: "Fetches the current stock quote from Alpha Vantage and sends an email with the stock information to your registered email address."
2419
2422
  }
2420
2423
  ]
@@ -2454,6 +2457,25 @@ var require_templates = __commonJS({
2454
2457
  preferredAuthType: "apikey",
2455
2458
  keywords: ["database", "cache", "redis", "key-value", "nosql", "api key"]
2456
2459
  },
2460
+ azure_sql: {
2461
+ name: "azure_sql",
2462
+ apiUrl: "sqlserver://<<host>>:1433;database=<<database>>",
2463
+ regex: "^.*(azure.*sql|sql.*azure|database\\.windows\\.net).*$",
2464
+ icon: "default",
2465
+ docsUrl: "https://learn.microsoft.com/en-us/azure/azure-sql/",
2466
+ preferredAuthType: "apikey",
2467
+ keywords: [
2468
+ "database",
2469
+ "sql",
2470
+ "azure",
2471
+ "query",
2472
+ "table",
2473
+ "schema",
2474
+ "connection",
2475
+ "mssql",
2476
+ "sqlserver"
2477
+ ]
2478
+ },
2457
2479
  stripe: {
2458
2480
  name: "stripe",
2459
2481
  apiUrl: "https://api.stripe.com",
@@ -2539,6 +2561,30 @@ var require_templates = __commonJS({
2539
2561
  "memberships"
2540
2562
  ]
2541
2563
  },
2564
+ hrworks: {
2565
+ name: "hrworks",
2566
+ apiUrl: "https://api.hrworks.de/v2",
2567
+ regex: "(^|.*\\b)(hr\\s?works|hrworks)(\\b.*|$)",
2568
+ icon: "default",
2569
+ docsUrl: "https://developers.hrworks.de/",
2570
+ preferredAuthType: "apikey",
2571
+ keywords: [
2572
+ "hr",
2573
+ "employee",
2574
+ "absence",
2575
+ "vacation",
2576
+ "payroll",
2577
+ "personnel",
2578
+ "time_tracking",
2579
+ "human_resources",
2580
+ "working_time",
2581
+ "attendance",
2582
+ "onboarding",
2583
+ "applicant_management",
2584
+ "travel_expenses",
2585
+ "sick_leave"
2586
+ ]
2587
+ },
2542
2588
  attio: {
2543
2589
  name: "attio",
2544
2590
  apiUrl: "https://api.attio.com/v2/",
@@ -2805,6 +2851,15 @@ var require_templates = __commonJS({
2805
2851
  "oauth"
2806
2852
  ]
2807
2853
  },
2854
+ granola: {
2855
+ name: "granola",
2856
+ apiUrl: "https://public-api.granola.ai",
2857
+ regex: "^.*granola.*$",
2858
+ icon: "default",
2859
+ docsUrl: "https://docs.granola.ai",
2860
+ preferredAuthType: "apikey",
2861
+ keywords: ["meeting", "notes", "transcript", "summary", "ai", "recording"]
2862
+ },
2808
2863
  googleDrive: {
2809
2864
  name: "googleDrive",
2810
2865
  apiUrl: "https://www.googleapis.com/drive/v3",
@@ -4306,6 +4361,58 @@ HEADERS: { "Authorization": "Bearer <<token>>", "Content-Type": "application/jso
4306
4361
  "api key"
4307
4362
  ]
4308
4363
  },
4364
+ creatio: {
4365
+ name: "creatio",
4366
+ apiUrl: "https://<<instance>>.creatio.com/0/odata",
4367
+ regex: "^(.*\\.)?creatio\\.com(/.*)?$",
4368
+ icon: "default",
4369
+ docsUrl: "https://academy.creatio.com/docs/developer/integrations_and_api/data_services/odata/overview",
4370
+ preferredAuthType: "oauth",
4371
+ oauth: {
4372
+ authUrl: "https://<<instance>>.creatio.com/0/connect/authorize",
4373
+ tokenUrl: "https://<<instance>>.creatio.com/0/connect/token",
4374
+ scopes: "offline_access",
4375
+ grant_type: "authorization_code"
4376
+ },
4377
+ systemSpecificInstructions: `Creatio uses OIDC-compliant OAuth endpoints. The standard /ServiceModel/AuthService.svc/Authorize and /rest/oauth/token endpoints are behind IIS session auth and will NOT work for OAuth flows \u2014 you MUST use the /0/connect/* OIDC endpoints instead.
4378
+
4379
+ To discover the correct endpoints for any Creatio instance, fetch: https://<instance>.creatio.com/0/.well-known/openid-configuration
4380
+
4381
+ This returns authorization_endpoint, token_endpoint, and other OIDC URLs.
4382
+
4383
+ IMPORTANT \u2014 Scopes:
4384
+ - "offline_access" gets you a refresh token but may not grant API access alone.
4385
+ - To get actual API access, the user needs the ApplicationAccess scope: "offline_access ApplicationAccess_<GUID>"
4386
+ - The GUID is found in Creatio: System Designer \u2192 Lookups \u2192 "OAuth resources" \u2192 Name column (strip dashes).
4387
+ - The OAuth app in Creatio must also have this resource added under its permitted resources.
4388
+
4389
+ OAuth App Setup in Creatio:
4390
+ 1. System Designer \u2192 "OAuth 2.0 integrated applications" \u2192 create app with grant type "On behalf of a user (authorization code)"
4391
+ 2. Set redirect URI to the superglue callback URL
4392
+ 3. Under the app's permitted resources, add the ApplicationAccess resource
4393
+ 4. Note the Client ID and Client Secret
4394
+
4395
+ API Base URLs:
4396
+ - OData 4: https://<instance>.creatio.com/0/odata/ (e.g., /0/odata/Contact)
4397
+ - OData 3: https://<instance>.creatio.com/0/ServiceModel/EntityDataService.svc/ (e.g., /EntityDataService.svc/ContactCollection)
4398
+ - Use Bearer token auth: Authorization: Bearer <access_token>`,
4399
+ keywords: [
4400
+ "contacts",
4401
+ "accounts",
4402
+ "leads",
4403
+ "opportunities",
4404
+ "activities",
4405
+ "cases",
4406
+ "orders",
4407
+ "products",
4408
+ "invoices",
4409
+ "campaigns",
4410
+ "crm",
4411
+ "bpm",
4412
+ "odata",
4413
+ "oauth"
4414
+ ]
4415
+ },
4309
4416
  sanity: {
4310
4417
  name: "sanity",
4311
4418
  apiUrl: "https://api.sanity.io",
@@ -4554,6 +4661,54 @@ HEADERS: { "Authorization": "Bearer <<token>>", "Content-Type": "application/jso
4554
4661
  "api key"
4555
4662
  ]
4556
4663
  },
4664
+ datahub: {
4665
+ name: "datahub",
4666
+ apiUrl: "https://{your-datahub-host}",
4667
+ regex: "^.*(datahub|acryl\\.datahub|datahubproject|datahub-gms|acryl\\.io).*$",
4668
+ icon: "lucide:library-big",
4669
+ docsUrl: "https://docs.datahub.com/docs/api/openapi/openapi-usage-guide",
4670
+ preferredAuthType: "apikey",
4671
+ keywords: [
4672
+ "metadata",
4673
+ "catalog",
4674
+ "data discovery",
4675
+ "lineage",
4676
+ "dataset",
4677
+ "dashboard",
4678
+ "ml model",
4679
+ "governance",
4680
+ "entities",
4681
+ "aspects",
4682
+ "urn",
4683
+ "relationships",
4684
+ "schema",
4685
+ "openapi",
4686
+ "gms",
4687
+ "ingestion",
4688
+ "acryl",
4689
+ "oidc",
4690
+ "api key"
4691
+ ],
4692
+ systemSpecificInstructions: `DataHub is a metadata catalog (discovery, lineage, governance, quality, contracts). Programmatic access for REST-first workflows is the OpenAPI surface on the Metadata Service (GMS), not the marketing or docs site.
4693
+
4694
+ OSS vs Cloud (brief): Self-hosted (open-source) means you run DataHub in your environment (Docker/K8s/Helm, etc.) and own URLs, upgrades, and networking. DataHub Cloud (Acryl) is a managed instance: you typically get https://<your-domain>.acryl.io, onboarding from the integrations team, optional AWS PrivateLink into your VPC, and UI login via admin invite or OIDC \u2014 same metadata model and APIs in principle, different hostname, auth onboarding, and who operates the plane. Always use the base URL you were given, not generic doc sites.
4695
+
4696
+ DataHub Cloud UI access: Admin users receive an invite link; OIDC uses your IdP\u2019s Client ID, Client Secret, and Discovery URL (must resolve to \u2026/.well-known/openid-configuration). Register redirect/callback https://<your-acryl-domain>.acryl.io/callback/oidc in the IdP. As of current Cloud docs, LDAP/SAML are not supported for that login path \u2014 confirm with Acryl if your requirements differ. Support: http://support.datahub.com/
4697
+
4698
+ Ingestion & discovery: Cloud uses push-based ingestion \u2014 run DataHub\u2019s agent inside your network so secrets stay local, with scheduled Python ingestion jobs pushing metadata to your instance. Day-to-day discovery is search and browse in the UI; OpenAPI/GraphQL/Rest.li read and write the same underlying graph.
4699
+
4700
+ Base URL (critical): OpenAPI is under /openapi/ on the GMS origin (or the UI origin if it proxies /openapi). Local quickstart: http://localhost:8080/openapi/swagger-ui/index.html \u2014 API base is scheme+host+port only (e.g. https://gms.yourcompany.com, your Cloud hostname, or a frontend that proxies GMS).
4701
+
4702
+ Verify the base: {base}/openapi/v3/api-docs or {base}/openapi/v3/api-docs.yaml. No global openApiUrl \u2014 in superglue, import from your instance\u2019s /openapi/v3/api-docs (or .yaml).
4703
+
4704
+ Authentication: REST examples use Authorization: Bearer <token>. Token issuance depends on edition (PATs, OIDC/session, etc.); follow DataHub\u2019s authentication and access-token docs for your deployment.
4705
+
4706
+ Main OpenAPI groups (paths under /openapi/): entities/v1 \u2014 upsert/read/delete entity+aspect (POST; ?createEntityIfNotExists=true for create-only; GET \u2026/latest?urns&aspectNames; DELETE ?urns&soft=). relationships/v1 \u2014 graph navigation. timeline \u2014 aspect history. platform \u2014 metadata events. v3 adds batch get (/v3/entity/{entityName}/batchGet), conditional writes, JSON Patch-style updates (see OpenAPI guide).
4707
+
4708
+ Identifiers are URN-centric (e.g. urn:li:dataset:(...)). Also GraphQL and Rest.li \u2014 see the official API overview to pick an interface.
4709
+
4710
+ References: https://docs.datahub.com/docs/features \u2014 product context; https://docs.datahub.com/docs/api/openapi/openapi-usage-guide \u2014 OpenAPI usage; https://docs.datahub.com/docs/managed-datahub/welcome-acryl \u2014 DataHub Cloud getting started (URL pattern, OIDC callback, ingestion); https://docs.datahub.com/docs/managed-datahub/managed-datahub-overview \u2014 OSS vs Cloud feature comparison.`
4711
+ },
4557
4712
  looker: {
4558
4713
  name: "looker",
4559
4714
  apiUrl: "https://{your-domain}.looker.com/api",
@@ -5365,7 +5520,7 @@ CUSTOM APIs: Publishers expose custom API pages at /api/{publisher}/{group}/{ver
5365
5520
  },
5366
5521
  googleAds: {
5367
5522
  name: "googleAds",
5368
- apiUrl: "https://googleads.googleapis.com/v20",
5523
+ apiUrl: "https://googleads.googleapis.com/v23",
5369
5524
  regex: "^.*(googleads\\.googleapis|developers\\.google\\.com/google-ads|adwords\\.google).*$",
5370
5525
  icon: "googleads",
5371
5526
  docsUrl: "https://developers.google.com/google-ads/api/docs/concepts/overview",
@@ -5373,11 +5528,24 @@ CUSTOM APIs: Publishers expose custom API pages at /api/{publisher}/{group}/{ver
5373
5528
  oauth: {
5374
5529
  authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
5375
5530
  tokenUrl: "https://oauth2.googleapis.com/token",
5376
- scopes: "https://www.googleapis.com/auth/adwords https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile openid"
5531
+ scopes: "https://www.googleapis.com/auth/adwords"
5377
5532
  },
5533
+ systemSpecificInstructions: `Google Ads API requires BOTH OAuth AND a developer token on every request.
5534
+
5535
+ REQUIRED HEADERS:
5536
+ - Authorization: Bearer <access_token>
5537
+ - developer-token: <22-char token from https://ads.google.com/aw/apicenter>
5538
+ - login-customer-id: <manager-account-id without hyphens> (only when calling through a manager account)
5539
+
5540
+ SETUP: User needs a Google Ads Manager account, a Google Cloud project with OAuth credentials, and a developer token (applied for via the API Center). New tokens start as test-only; production access requires a follow-up application.
5541
+
5542
+ QUERYING (GAQL): Use Google Ads Query Language via:
5543
+ - POST /v23/customers/{customerId}/googleAds:searchStream (streaming, recommended)
5544
+ - POST /v23/customers/{customerId}/googleAds:search (paginated)
5545
+ Example: SELECT campaign.name, metrics.impressions FROM campaign WHERE segments.date DURING LAST_30_DAYS`,
5378
5546
  keywords: [
5379
5547
  "campaigns",
5380
- "ad groups",
5548
+ "ad_groups",
5381
5549
  "ads",
5382
5550
  "keywords",
5383
5551
  "GAQL",
@@ -5390,6 +5558,9 @@ CUSTOM APIs: Publishers expose custom API pages at /api/{publisher}/{group}/{ver
5390
5558
  "accounts",
5391
5559
  "billing",
5392
5560
  "targeting",
5561
+ "search_terms",
5562
+ "metrics",
5563
+ "segments",
5393
5564
  "oauth"
5394
5565
  ]
5395
5566
  },
@@ -5446,6 +5617,33 @@ CUSTOM APIs: Publishers expose custom API pages at /api/{publisher}/{group}/{ver
5446
5617
  "api key"
5447
5618
  ]
5448
5619
  },
5620
+ circleback: {
5621
+ name: "circleback",
5622
+ apiUrl: "https://app.circleback.ai",
5623
+ regex: "^.*circleback.*$",
5624
+ icon: "default",
5625
+ docsUrl: "https://support.circleback.ai/en/articles/13249081-circleback-mcp",
5626
+ preferredAuthType: "oauth",
5627
+ systemSpecificInstructions: `Circleback has NO traditional REST API. Data access is exclusively via their MCP server.
5628
+
5629
+ MCP ENDPOINT: https://app.circleback.ai/api/mcp
5630
+ PROTOCOL: JSON-RPC 2.0 over Streamable HTTP transport
5631
+ AUTH: OAuth 2.0 with dynamic client registration (no app registration needed).
5632
+
5633
+ AVAILABLE DATA: meetings, transcripts, action items, calendar events, emails, people, companies.`,
5634
+ keywords: [
5635
+ "meetings",
5636
+ "transcripts",
5637
+ "notes",
5638
+ "action_items",
5639
+ "calendar_events",
5640
+ "attendees",
5641
+ "summaries",
5642
+ "people",
5643
+ "companies",
5644
+ "emails"
5645
+ ]
5646
+ },
5449
5647
  firecrawl: {
5450
5648
  name: "firecrawl",
5451
5649
  apiUrl: "https://api.firecrawl.dev/v1",
@@ -5710,6 +5908,8 @@ var require_type_utils = __commonJS({
5710
5908
  exports2.PAGINATION_TYPE_MAP = void 0;
5711
5909
  exports2.mapPaginationType = mapPaginationType;
5712
5910
  exports2.mapFailureBehavior = mapFailureBehavior;
5911
+ exports2.validateToolStructure = validateToolStructure;
5912
+ var types_js_1 = require_types();
5713
5913
  exports2.PAGINATION_TYPE_MAP = {
5714
5914
  OFFSET_BASED: "offsetBased",
5715
5915
  PAGE_BASED: "pageBased",
@@ -5729,6 +5929,50 @@ var require_type_utils = __commonJS({
5729
5929
  return void 0;
5730
5930
  return internal.toLowerCase();
5731
5931
  }
5932
+ function validateToolStructure(tool) {
5933
+ if (!tool || typeof tool !== "object") {
5934
+ return { valid: false, error: "Tool must be an object" };
5935
+ }
5936
+ const candidate = tool;
5937
+ if (!candidate.id || typeof candidate.id !== "string") {
5938
+ return { valid: false, error: "Tool must have a valid 'id' string" };
5939
+ }
5940
+ if (!Array.isArray(candidate.steps)) {
5941
+ return { valid: false, error: "Tool must have a 'steps' array" };
5942
+ }
5943
+ if (candidate.steps.length === 0 && !candidate.outputTransform) {
5944
+ return { valid: false, error: "Tool must have at least one step or an outputTransform" };
5945
+ }
5946
+ for (let i = 0; i < candidate.steps.length; i++) {
5947
+ const step = candidate.steps[i];
5948
+ const stepLabel = step?.id ? `Step ${i + 1} (${step.id})` : `Step ${i + 1}`;
5949
+ if (!step?.id) {
5950
+ return { valid: false, error: `Step ${i + 1}: missing 'id'` };
5951
+ }
5952
+ if (!step.config) {
5953
+ return { valid: false, error: `${stepLabel}: missing 'config'` };
5954
+ }
5955
+ if ((0, types_js_1.isTransformConfig)(step.config)) {
5956
+ if (!step.config.transformCode) {
5957
+ return {
5958
+ valid: false,
5959
+ error: `${stepLabel}: transform step missing 'transformCode'`
5960
+ };
5961
+ }
5962
+ continue;
5963
+ }
5964
+ if (!(0, types_js_1.isRequestConfig)(step.config)) {
5965
+ return {
5966
+ valid: false,
5967
+ error: `${stepLabel}: unknown step config type`
5968
+ };
5969
+ }
5970
+ if (typeof step.config.url !== "string" || step.config.url.trim().length === 0) {
5971
+ return { valid: false, error: `${stepLabel}: request step missing 'url'` };
5972
+ }
5973
+ }
5974
+ return { valid: true };
5975
+ }
5732
5976
  }
5733
5977
  });
5734
5978
 
@@ -21697,12 +21941,18 @@ var require_superglue_client = __commonJS({
21697
21941
  const response = await this.restRequest("GET", `/v1/tools?limit=${limit}&page=${page}${archiveParam}`);
21698
21942
  return { items: response.data, total: response.total };
21699
21943
  }
21944
+ async createWorkflow(id, input) {
21945
+ return this.restRequest("POST", "/v1/tools", { ...input, id });
21946
+ }
21947
+ async updateWorkflow(id, input) {
21948
+ return this.restRequest("PUT", `/v1/tools/${encodeURIComponent(id)}`, input);
21949
+ }
21700
21950
  async upsertWorkflow(id, input) {
21701
21951
  const existing = await this.getWorkflow(id);
21702
21952
  if (existing) {
21703
- return this.restRequest("PUT", `/v1/tools/${encodeURIComponent(id)}`, input);
21953
+ return this.updateWorkflow(id, input);
21704
21954
  } else {
21705
- return this.restRequest("POST", "/v1/tools", { id, ...input });
21955
+ return this.createWorkflow(id, input);
21706
21956
  }
21707
21957
  }
21708
21958
  async deleteWorkflow(id) {
package/dist/dist/cli.js CHANGED
@@ -1925,7 +1925,9 @@ var require_types = __commonJS({
1925
1925
  RemoveScope2["ENTRY"] = "ENTRY";
1926
1926
  })(RemoveScope || (exports2.RemoveScope = RemoveScope = {}));
1927
1927
  function isRequestConfig(config) {
1928
- return config?.type === "request" || !config?.type;
1928
+ if (!config || typeof config !== "object")
1929
+ return false;
1930
+ return config.type === "request" || !("type" in config) || config.type === void 0;
1929
1931
  }
1930
1932
  function isTransformConfig(config) {
1931
1933
  return config?.type === "transform";
@@ -2389,7 +2391,7 @@ Use parameterized queries with $1, $2, etc. placeholders:
2389
2391
 
2390
2392
  <div style="margin-top: 24px; padding: 20px; background: #fefce8; border-radius: 12px; border: 1px solid #fef08a;">
2391
2393
  <p style="margin: 0; color: #854d0e; font-size: 14px;">
2392
- <strong>\u{1F4A1} This is a demo tool!</strong> You just ran your first superglue workflow.
2394
+ <strong>\u{1F4A1} This is a demo tool!</strong> You just ran your first superglue tool.
2393
2395
  Edit this tool or create your own to automate any API integration.
2394
2396
  </p>
2395
2397
  </div>
@@ -2415,6 +2417,7 @@ Use parameterized queries with $1, $2, etc. placeholders:
2415
2417
  }
2416
2418
  }
2417
2419
  },
2420
+ outputTransform: `(sourceData) => { const quote = sourceData.fetchStock?.data?.["Global Quote"] || {}; return { symbol: quote["01. symbol"] || sourceData.symbol || "AAPL", price: parseFloat(quote["05. price"] || "0").toFixed(2), change: quote["09. change"] || "0", changePercent: quote["10. change percent"] || "0%", volume: parseInt(quote["06. volume"] || "0").toLocaleString(), tradingDay: quote["07. latest trading day"] || "N/A", emailSent: sourceData.sendEmail?.success || false }; }`,
2418
2421
  instruction: "Fetches the current stock quote from Alpha Vantage and sends an email with the stock information to your registered email address."
2419
2422
  }
2420
2423
  ]
@@ -2454,6 +2457,25 @@ var require_templates = __commonJS({
2454
2457
  preferredAuthType: "apikey",
2455
2458
  keywords: ["database", "cache", "redis", "key-value", "nosql", "api key"]
2456
2459
  },
2460
+ azure_sql: {
2461
+ name: "azure_sql",
2462
+ apiUrl: "sqlserver://<<host>>:1433;database=<<database>>",
2463
+ regex: "^.*(azure.*sql|sql.*azure|database\\.windows\\.net).*$",
2464
+ icon: "default",
2465
+ docsUrl: "https://learn.microsoft.com/en-us/azure/azure-sql/",
2466
+ preferredAuthType: "apikey",
2467
+ keywords: [
2468
+ "database",
2469
+ "sql",
2470
+ "azure",
2471
+ "query",
2472
+ "table",
2473
+ "schema",
2474
+ "connection",
2475
+ "mssql",
2476
+ "sqlserver"
2477
+ ]
2478
+ },
2457
2479
  stripe: {
2458
2480
  name: "stripe",
2459
2481
  apiUrl: "https://api.stripe.com",
@@ -2539,6 +2561,30 @@ var require_templates = __commonJS({
2539
2561
  "memberships"
2540
2562
  ]
2541
2563
  },
2564
+ hrworks: {
2565
+ name: "hrworks",
2566
+ apiUrl: "https://api.hrworks.de/v2",
2567
+ regex: "(^|.*\\b)(hr\\s?works|hrworks)(\\b.*|$)",
2568
+ icon: "default",
2569
+ docsUrl: "https://developers.hrworks.de/",
2570
+ preferredAuthType: "apikey",
2571
+ keywords: [
2572
+ "hr",
2573
+ "employee",
2574
+ "absence",
2575
+ "vacation",
2576
+ "payroll",
2577
+ "personnel",
2578
+ "time_tracking",
2579
+ "human_resources",
2580
+ "working_time",
2581
+ "attendance",
2582
+ "onboarding",
2583
+ "applicant_management",
2584
+ "travel_expenses",
2585
+ "sick_leave"
2586
+ ]
2587
+ },
2542
2588
  attio: {
2543
2589
  name: "attio",
2544
2590
  apiUrl: "https://api.attio.com/v2/",
@@ -2805,6 +2851,15 @@ var require_templates = __commonJS({
2805
2851
  "oauth"
2806
2852
  ]
2807
2853
  },
2854
+ granola: {
2855
+ name: "granola",
2856
+ apiUrl: "https://public-api.granola.ai",
2857
+ regex: "^.*granola.*$",
2858
+ icon: "default",
2859
+ docsUrl: "https://docs.granola.ai",
2860
+ preferredAuthType: "apikey",
2861
+ keywords: ["meeting", "notes", "transcript", "summary", "ai", "recording"]
2862
+ },
2808
2863
  googleDrive: {
2809
2864
  name: "googleDrive",
2810
2865
  apiUrl: "https://www.googleapis.com/drive/v3",
@@ -4306,6 +4361,58 @@ HEADERS: { "Authorization": "Bearer <<token>>", "Content-Type": "application/jso
4306
4361
  "api key"
4307
4362
  ]
4308
4363
  },
4364
+ creatio: {
4365
+ name: "creatio",
4366
+ apiUrl: "https://<<instance>>.creatio.com/0/odata",
4367
+ regex: "^(.*\\.)?creatio\\.com(/.*)?$",
4368
+ icon: "default",
4369
+ docsUrl: "https://academy.creatio.com/docs/developer/integrations_and_api/data_services/odata/overview",
4370
+ preferredAuthType: "oauth",
4371
+ oauth: {
4372
+ authUrl: "https://<<instance>>.creatio.com/0/connect/authorize",
4373
+ tokenUrl: "https://<<instance>>.creatio.com/0/connect/token",
4374
+ scopes: "offline_access",
4375
+ grant_type: "authorization_code"
4376
+ },
4377
+ systemSpecificInstructions: `Creatio uses OIDC-compliant OAuth endpoints. The standard /ServiceModel/AuthService.svc/Authorize and /rest/oauth/token endpoints are behind IIS session auth and will NOT work for OAuth flows \u2014 you MUST use the /0/connect/* OIDC endpoints instead.
4378
+
4379
+ To discover the correct endpoints for any Creatio instance, fetch: https://<instance>.creatio.com/0/.well-known/openid-configuration
4380
+
4381
+ This returns authorization_endpoint, token_endpoint, and other OIDC URLs.
4382
+
4383
+ IMPORTANT \u2014 Scopes:
4384
+ - "offline_access" gets you a refresh token but may not grant API access alone.
4385
+ - To get actual API access, the user needs the ApplicationAccess scope: "offline_access ApplicationAccess_<GUID>"
4386
+ - The GUID is found in Creatio: System Designer \u2192 Lookups \u2192 "OAuth resources" \u2192 Name column (strip dashes).
4387
+ - The OAuth app in Creatio must also have this resource added under its permitted resources.
4388
+
4389
+ OAuth App Setup in Creatio:
4390
+ 1. System Designer \u2192 "OAuth 2.0 integrated applications" \u2192 create app with grant type "On behalf of a user (authorization code)"
4391
+ 2. Set redirect URI to the superglue callback URL
4392
+ 3. Under the app's permitted resources, add the ApplicationAccess resource
4393
+ 4. Note the Client ID and Client Secret
4394
+
4395
+ API Base URLs:
4396
+ - OData 4: https://<instance>.creatio.com/0/odata/ (e.g., /0/odata/Contact)
4397
+ - OData 3: https://<instance>.creatio.com/0/ServiceModel/EntityDataService.svc/ (e.g., /EntityDataService.svc/ContactCollection)
4398
+ - Use Bearer token auth: Authorization: Bearer <access_token>`,
4399
+ keywords: [
4400
+ "contacts",
4401
+ "accounts",
4402
+ "leads",
4403
+ "opportunities",
4404
+ "activities",
4405
+ "cases",
4406
+ "orders",
4407
+ "products",
4408
+ "invoices",
4409
+ "campaigns",
4410
+ "crm",
4411
+ "bpm",
4412
+ "odata",
4413
+ "oauth"
4414
+ ]
4415
+ },
4309
4416
  sanity: {
4310
4417
  name: "sanity",
4311
4418
  apiUrl: "https://api.sanity.io",
@@ -4554,6 +4661,54 @@ HEADERS: { "Authorization": "Bearer <<token>>", "Content-Type": "application/jso
4554
4661
  "api key"
4555
4662
  ]
4556
4663
  },
4664
+ datahub: {
4665
+ name: "datahub",
4666
+ apiUrl: "https://{your-datahub-host}",
4667
+ regex: "^.*(datahub|acryl\\.datahub|datahubproject|datahub-gms|acryl\\.io).*$",
4668
+ icon: "lucide:library-big",
4669
+ docsUrl: "https://docs.datahub.com/docs/api/openapi/openapi-usage-guide",
4670
+ preferredAuthType: "apikey",
4671
+ keywords: [
4672
+ "metadata",
4673
+ "catalog",
4674
+ "data discovery",
4675
+ "lineage",
4676
+ "dataset",
4677
+ "dashboard",
4678
+ "ml model",
4679
+ "governance",
4680
+ "entities",
4681
+ "aspects",
4682
+ "urn",
4683
+ "relationships",
4684
+ "schema",
4685
+ "openapi",
4686
+ "gms",
4687
+ "ingestion",
4688
+ "acryl",
4689
+ "oidc",
4690
+ "api key"
4691
+ ],
4692
+ systemSpecificInstructions: `DataHub is a metadata catalog (discovery, lineage, governance, quality, contracts). Programmatic access for REST-first workflows is the OpenAPI surface on the Metadata Service (GMS), not the marketing or docs site.
4693
+
4694
+ OSS vs Cloud (brief): Self-hosted (open-source) means you run DataHub in your environment (Docker/K8s/Helm, etc.) and own URLs, upgrades, and networking. DataHub Cloud (Acryl) is a managed instance: you typically get https://<your-domain>.acryl.io, onboarding from the integrations team, optional AWS PrivateLink into your VPC, and UI login via admin invite or OIDC \u2014 same metadata model and APIs in principle, different hostname, auth onboarding, and who operates the plane. Always use the base URL you were given, not generic doc sites.
4695
+
4696
+ DataHub Cloud UI access: Admin users receive an invite link; OIDC uses your IdP\u2019s Client ID, Client Secret, and Discovery URL (must resolve to \u2026/.well-known/openid-configuration). Register redirect/callback https://<your-acryl-domain>.acryl.io/callback/oidc in the IdP. As of current Cloud docs, LDAP/SAML are not supported for that login path \u2014 confirm with Acryl if your requirements differ. Support: http://support.datahub.com/
4697
+
4698
+ Ingestion & discovery: Cloud uses push-based ingestion \u2014 run DataHub\u2019s agent inside your network so secrets stay local, with scheduled Python ingestion jobs pushing metadata to your instance. Day-to-day discovery is search and browse in the UI; OpenAPI/GraphQL/Rest.li read and write the same underlying graph.
4699
+
4700
+ Base URL (critical): OpenAPI is under /openapi/ on the GMS origin (or the UI origin if it proxies /openapi). Local quickstart: http://localhost:8080/openapi/swagger-ui/index.html \u2014 API base is scheme+host+port only (e.g. https://gms.yourcompany.com, your Cloud hostname, or a frontend that proxies GMS).
4701
+
4702
+ Verify the base: {base}/openapi/v3/api-docs or {base}/openapi/v3/api-docs.yaml. No global openApiUrl \u2014 in superglue, import from your instance\u2019s /openapi/v3/api-docs (or .yaml).
4703
+
4704
+ Authentication: REST examples use Authorization: Bearer <token>. Token issuance depends on edition (PATs, OIDC/session, etc.); follow DataHub\u2019s authentication and access-token docs for your deployment.
4705
+
4706
+ Main OpenAPI groups (paths under /openapi/): entities/v1 \u2014 upsert/read/delete entity+aspect (POST; ?createEntityIfNotExists=true for create-only; GET \u2026/latest?urns&aspectNames; DELETE ?urns&soft=). relationships/v1 \u2014 graph navigation. timeline \u2014 aspect history. platform \u2014 metadata events. v3 adds batch get (/v3/entity/{entityName}/batchGet), conditional writes, JSON Patch-style updates (see OpenAPI guide).
4707
+
4708
+ Identifiers are URN-centric (e.g. urn:li:dataset:(...)). Also GraphQL and Rest.li \u2014 see the official API overview to pick an interface.
4709
+
4710
+ References: https://docs.datahub.com/docs/features \u2014 product context; https://docs.datahub.com/docs/api/openapi/openapi-usage-guide \u2014 OpenAPI usage; https://docs.datahub.com/docs/managed-datahub/welcome-acryl \u2014 DataHub Cloud getting started (URL pattern, OIDC callback, ingestion); https://docs.datahub.com/docs/managed-datahub/managed-datahub-overview \u2014 OSS vs Cloud feature comparison.`
4711
+ },
4557
4712
  looker: {
4558
4713
  name: "looker",
4559
4714
  apiUrl: "https://{your-domain}.looker.com/api",
@@ -5365,7 +5520,7 @@ CUSTOM APIs: Publishers expose custom API pages at /api/{publisher}/{group}/{ver
5365
5520
  },
5366
5521
  googleAds: {
5367
5522
  name: "googleAds",
5368
- apiUrl: "https://googleads.googleapis.com/v20",
5523
+ apiUrl: "https://googleads.googleapis.com/v23",
5369
5524
  regex: "^.*(googleads\\.googleapis|developers\\.google\\.com/google-ads|adwords\\.google).*$",
5370
5525
  icon: "googleads",
5371
5526
  docsUrl: "https://developers.google.com/google-ads/api/docs/concepts/overview",
@@ -5373,11 +5528,24 @@ CUSTOM APIs: Publishers expose custom API pages at /api/{publisher}/{group}/{ver
5373
5528
  oauth: {
5374
5529
  authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
5375
5530
  tokenUrl: "https://oauth2.googleapis.com/token",
5376
- scopes: "https://www.googleapis.com/auth/adwords https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile openid"
5531
+ scopes: "https://www.googleapis.com/auth/adwords"
5377
5532
  },
5533
+ systemSpecificInstructions: `Google Ads API requires BOTH OAuth AND a developer token on every request.
5534
+
5535
+ REQUIRED HEADERS:
5536
+ - Authorization: Bearer <access_token>
5537
+ - developer-token: <22-char token from https://ads.google.com/aw/apicenter>
5538
+ - login-customer-id: <manager-account-id without hyphens> (only when calling through a manager account)
5539
+
5540
+ SETUP: User needs a Google Ads Manager account, a Google Cloud project with OAuth credentials, and a developer token (applied for via the API Center). New tokens start as test-only; production access requires a follow-up application.
5541
+
5542
+ QUERYING (GAQL): Use Google Ads Query Language via:
5543
+ - POST /v23/customers/{customerId}/googleAds:searchStream (streaming, recommended)
5544
+ - POST /v23/customers/{customerId}/googleAds:search (paginated)
5545
+ Example: SELECT campaign.name, metrics.impressions FROM campaign WHERE segments.date DURING LAST_30_DAYS`,
5378
5546
  keywords: [
5379
5547
  "campaigns",
5380
- "ad groups",
5548
+ "ad_groups",
5381
5549
  "ads",
5382
5550
  "keywords",
5383
5551
  "GAQL",
@@ -5390,6 +5558,9 @@ CUSTOM APIs: Publishers expose custom API pages at /api/{publisher}/{group}/{ver
5390
5558
  "accounts",
5391
5559
  "billing",
5392
5560
  "targeting",
5561
+ "search_terms",
5562
+ "metrics",
5563
+ "segments",
5393
5564
  "oauth"
5394
5565
  ]
5395
5566
  },
@@ -5446,6 +5617,33 @@ CUSTOM APIs: Publishers expose custom API pages at /api/{publisher}/{group}/{ver
5446
5617
  "api key"
5447
5618
  ]
5448
5619
  },
5620
+ circleback: {
5621
+ name: "circleback",
5622
+ apiUrl: "https://app.circleback.ai",
5623
+ regex: "^.*circleback.*$",
5624
+ icon: "default",
5625
+ docsUrl: "https://support.circleback.ai/en/articles/13249081-circleback-mcp",
5626
+ preferredAuthType: "oauth",
5627
+ systemSpecificInstructions: `Circleback has NO traditional REST API. Data access is exclusively via their MCP server.
5628
+
5629
+ MCP ENDPOINT: https://app.circleback.ai/api/mcp
5630
+ PROTOCOL: JSON-RPC 2.0 over Streamable HTTP transport
5631
+ AUTH: OAuth 2.0 with dynamic client registration (no app registration needed).
5632
+
5633
+ AVAILABLE DATA: meetings, transcripts, action items, calendar events, emails, people, companies.`,
5634
+ keywords: [
5635
+ "meetings",
5636
+ "transcripts",
5637
+ "notes",
5638
+ "action_items",
5639
+ "calendar_events",
5640
+ "attendees",
5641
+ "summaries",
5642
+ "people",
5643
+ "companies",
5644
+ "emails"
5645
+ ]
5646
+ },
5449
5647
  firecrawl: {
5450
5648
  name: "firecrawl",
5451
5649
  apiUrl: "https://api.firecrawl.dev/v1",
@@ -5710,6 +5908,8 @@ var require_type_utils = __commonJS({
5710
5908
  exports2.PAGINATION_TYPE_MAP = void 0;
5711
5909
  exports2.mapPaginationType = mapPaginationType;
5712
5910
  exports2.mapFailureBehavior = mapFailureBehavior;
5911
+ exports2.validateToolStructure = validateToolStructure;
5912
+ var types_js_1 = require_types();
5713
5913
  exports2.PAGINATION_TYPE_MAP = {
5714
5914
  OFFSET_BASED: "offsetBased",
5715
5915
  PAGE_BASED: "pageBased",
@@ -5729,6 +5929,50 @@ var require_type_utils = __commonJS({
5729
5929
  return void 0;
5730
5930
  return internal.toLowerCase();
5731
5931
  }
5932
+ function validateToolStructure(tool) {
5933
+ if (!tool || typeof tool !== "object") {
5934
+ return { valid: false, error: "Tool must be an object" };
5935
+ }
5936
+ const candidate = tool;
5937
+ if (!candidate.id || typeof candidate.id !== "string") {
5938
+ return { valid: false, error: "Tool must have a valid 'id' string" };
5939
+ }
5940
+ if (!Array.isArray(candidate.steps)) {
5941
+ return { valid: false, error: "Tool must have a 'steps' array" };
5942
+ }
5943
+ if (candidate.steps.length === 0 && !candidate.outputTransform) {
5944
+ return { valid: false, error: "Tool must have at least one step or an outputTransform" };
5945
+ }
5946
+ for (let i = 0; i < candidate.steps.length; i++) {
5947
+ const step = candidate.steps[i];
5948
+ const stepLabel = step?.id ? `Step ${i + 1} (${step.id})` : `Step ${i + 1}`;
5949
+ if (!step?.id) {
5950
+ return { valid: false, error: `Step ${i + 1}: missing 'id'` };
5951
+ }
5952
+ if (!step.config) {
5953
+ return { valid: false, error: `${stepLabel}: missing 'config'` };
5954
+ }
5955
+ if ((0, types_js_1.isTransformConfig)(step.config)) {
5956
+ if (!step.config.transformCode) {
5957
+ return {
5958
+ valid: false,
5959
+ error: `${stepLabel}: transform step missing 'transformCode'`
5960
+ };
5961
+ }
5962
+ continue;
5963
+ }
5964
+ if (!(0, types_js_1.isRequestConfig)(step.config)) {
5965
+ return {
5966
+ valid: false,
5967
+ error: `${stepLabel}: unknown step config type`
5968
+ };
5969
+ }
5970
+ if (typeof step.config.url !== "string" || step.config.url.trim().length === 0) {
5971
+ return { valid: false, error: `${stepLabel}: request step missing 'url'` };
5972
+ }
5973
+ }
5974
+ return { valid: true };
5975
+ }
5732
5976
  }
5733
5977
  });
5734
5978
 
@@ -21697,12 +21941,18 @@ var require_superglue_client = __commonJS({
21697
21941
  const response = await this.restRequest("GET", `/v1/tools?limit=${limit}&page=${page}${archiveParam}`);
21698
21942
  return { items: response.data, total: response.total };
21699
21943
  }
21944
+ async createWorkflow(id, input) {
21945
+ return this.restRequest("POST", "/v1/tools", { ...input, id });
21946
+ }
21947
+ async updateWorkflow(id, input) {
21948
+ return this.restRequest("PUT", `/v1/tools/${encodeURIComponent(id)}`, input);
21949
+ }
21700
21950
  async upsertWorkflow(id, input) {
21701
21951
  const existing = await this.getWorkflow(id);
21702
21952
  if (existing) {
21703
- return this.restRequest("PUT", `/v1/tools/${encodeURIComponent(id)}`, input);
21953
+ return this.updateWorkflow(id, input);
21704
21954
  } else {
21705
- return this.restRequest("POST", "/v1/tools", { id, ...input });
21955
+ return this.createWorkflow(id, input);
21706
21956
  }
21707
21957
  }
21708
21958
  async deleteWorkflow(id) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superglue/cli",
3
- "version": "1.1.14",
3
+ "version": "1.1.16",
4
4
  "bin": {
5
5
  "sg": "./dist/cli.js"
6
6
  },