@superglue/cli 1.1.0 → 1.1.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.
package/dist/cli.js CHANGED
@@ -1751,6 +1751,7 @@ var require_types = __commonJS({
1751
1751
  exports2.isRequestConfig = isRequestConfig;
1752
1752
  exports2.isTransformConfig = isTransformConfig;
1753
1753
  exports2.getToolSystemIds = getToolSystemIds;
1754
+ exports2.isProductionSystem = isProductionSystem;
1754
1755
  var UserRole;
1755
1756
  (function(UserRole2) {
1756
1757
  UserRole2["ADMIN"] = "admin";
@@ -1849,15 +1850,16 @@ var require_types = __commonJS({
1849
1850
  RunStatus2["FAILED"] = "FAILED";
1850
1851
  RunStatus2["ABORTED"] = "ABORTED";
1851
1852
  })(RunStatus || (exports2.RunStatus = RunStatus = {}));
1852
- var RequestSource;
1853
- (function(RequestSource2) {
1854
- RequestSource2["API"] = "api";
1855
- RequestSource2["FRONTEND"] = "frontend";
1856
- RequestSource2["SCHEDULER"] = "scheduler";
1857
- RequestSource2["MCP"] = "mcp";
1858
- RequestSource2["TOOL_CHAIN"] = "tool-chain";
1859
- RequestSource2["WEBHOOK"] = "webhook";
1860
- })(RequestSource || (exports2.RequestSource = RequestSource = {}));
1853
+ var RequestSource2;
1854
+ (function(RequestSource3) {
1855
+ RequestSource3["API"] = "api";
1856
+ RequestSource3["FRONTEND"] = "frontend";
1857
+ RequestSource3["SCHEDULER"] = "scheduler";
1858
+ RequestSource3["MCP"] = "mcp";
1859
+ RequestSource3["TOOL_CHAIN"] = "tool-chain";
1860
+ RequestSource3["WEBHOOK"] = "webhook";
1861
+ RequestSource3["CLI"] = "cli";
1862
+ })(RequestSource2 || (exports2.RequestSource = RequestSource2 = {}));
1861
1863
  var FilterTarget;
1862
1864
  (function(FilterTarget2) {
1863
1865
  FilterTarget2["KEYS"] = "KEYS";
@@ -1893,6 +1895,9 @@ var require_types = __commonJS({
1893
1895
  }
1894
1896
  return Array.from(ids);
1895
1897
  }
1898
+ function isProductionSystem(system) {
1899
+ return system.environment !== "dev";
1900
+ }
1896
1901
  var DiscoveryRunStatus;
1897
1902
  (function(DiscoveryRunStatus2) {
1898
1903
  DiscoveryRunStatus2["PENDING"] = "PENDING";
@@ -2981,10 +2986,15 @@ If the user has or creates an OAuth app in their Google Cloud project:
2981
2986
  4. After system creation, use authenticate_oauth - user completes Google sign-in in popup
2982
2987
  5. Superglue auto-refreshes tokens - no manual token management needed
2983
2988
 
2984
- OPTION 2: Service Account Token (Manual refresh required)
2985
- If the user has a service account JSON file:
2986
- - Superglue does NOT support JWT token generation from service account JSON (on roadmap)
2987
- - User must generate an access token on their machine using gcloud CLI:
2989
+ OPTION 2: Service Account JWT (Advanced)
2990
+ If the user has a service account JSON file, you can generate JWTs dynamically using a transform step:
2991
+ - Extract private_key and client_email from the service account JSON
2992
+ - Build the JWT header and claims, then sign with crypto.sign('sha256', data, privateKey, 'base64url')
2993
+ - Exchange the JWT for an access token via POST to https://oauth2.googleapis.com/token
2994
+
2995
+ OPTION 3: Service Account Token via CLI (Manual refresh required)
2996
+ If the user prefers to generate tokens externally:
2997
+ - User generates an access token on their machine using gcloud CLI:
2988
2998
  1. Activate the service account: gcloud auth activate-service-account --key-file=/path/to/service-account.json
2989
2999
  2. Print the token: gcloud auth print-access-token
2990
3000
  - The token is valid for 1 hour only
@@ -8813,8 +8823,8 @@ var require_luxon = __commonJS({
8813
8823
  let current = null, currentFull = "", bracketed = false;
8814
8824
  const splits = [];
8815
8825
  for (let i = 0; i < fmt.length; i++) {
8816
- const c2 = fmt.charAt(i);
8817
- if (c2 === "'") {
8826
+ const c3 = fmt.charAt(i);
8827
+ if (c3 === "'") {
8818
8828
  if (currentFull.length > 0 || bracketed) {
8819
8829
  splits.push({
8820
8830
  literal: bracketed || /^\s+$/.test(currentFull),
@@ -8825,9 +8835,9 @@ var require_luxon = __commonJS({
8825
8835
  currentFull = "";
8826
8836
  bracketed = !bracketed;
8827
8837
  } else if (bracketed) {
8828
- currentFull += c2;
8829
- } else if (c2 === current) {
8830
- currentFull += c2;
8838
+ currentFull += c3;
8839
+ } else if (c3 === current) {
8840
+ currentFull += c3;
8831
8841
  } else {
8832
8842
  if (currentFull.length > 0) {
8833
8843
  splits.push({
@@ -8835,8 +8845,8 @@ var require_luxon = __commonJS({
8835
8845
  val: currentFull
8836
8846
  });
8837
8847
  }
8838
- currentFull = c2;
8839
- current = c2;
8848
+ currentFull = c3;
8849
+ current = c3;
8840
8850
  }
8841
8851
  }
8842
8852
  if (currentFull.length > 0) {
@@ -11518,7 +11528,7 @@ var require_luxon = __commonJS({
11518
11528
  return fixOffset(objToLocalTS(obj), offset2, zone);
11519
11529
  }
11520
11530
  function adjustTime(inst, dur) {
11521
- const oPre = inst.o, year = inst.c.year + Math.trunc(dur.years), month = inst.c.month + Math.trunc(dur.months) + Math.trunc(dur.quarters) * 3, c2 = {
11531
+ const oPre = inst.o, year = inst.c.year + Math.trunc(dur.years), month = inst.c.month + Math.trunc(dur.months) + Math.trunc(dur.quarters) * 3, c3 = {
11522
11532
  ...inst.c,
11523
11533
  year,
11524
11534
  month,
@@ -11533,7 +11543,7 @@ var require_luxon = __commonJS({
11533
11543
  minutes: dur.minutes,
11534
11544
  seconds: dur.seconds,
11535
11545
  milliseconds: dur.milliseconds
11536
- }).as("milliseconds"), localTS = objToLocalTS(c2);
11546
+ }).as("milliseconds"), localTS = objToLocalTS(c3);
11537
11547
  let [ts, o] = fixOffset(localTS, oPre, inst.zone);
11538
11548
  if (millisToAdd !== 0) {
11539
11549
  ts += millisToAdd;
@@ -11568,72 +11578,72 @@ var require_luxon = __commonJS({
11568
11578
  }
11569
11579
  function toISODate(o, extended, precision) {
11570
11580
  const longFormat = o.c.year > 9999 || o.c.year < 0;
11571
- let c2 = "";
11572
- if (longFormat && o.c.year >= 0) c2 += "+";
11573
- c2 += padStart(o.c.year, longFormat ? 6 : 4);
11574
- if (precision === "year") return c2;
11581
+ let c3 = "";
11582
+ if (longFormat && o.c.year >= 0) c3 += "+";
11583
+ c3 += padStart(o.c.year, longFormat ? 6 : 4);
11584
+ if (precision === "year") return c3;
11575
11585
  if (extended) {
11576
- c2 += "-";
11577
- c2 += padStart(o.c.month);
11578
- if (precision === "month") return c2;
11579
- c2 += "-";
11586
+ c3 += "-";
11587
+ c3 += padStart(o.c.month);
11588
+ if (precision === "month") return c3;
11589
+ c3 += "-";
11580
11590
  } else {
11581
- c2 += padStart(o.c.month);
11582
- if (precision === "month") return c2;
11591
+ c3 += padStart(o.c.month);
11592
+ if (precision === "month") return c3;
11583
11593
  }
11584
- c2 += padStart(o.c.day);
11585
- return c2;
11594
+ c3 += padStart(o.c.day);
11595
+ return c3;
11586
11596
  }
11587
11597
  function toISOTime(o, extended, suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision) {
11588
- let showSeconds = !suppressSeconds || o.c.millisecond !== 0 || o.c.second !== 0, c2 = "";
11598
+ let showSeconds = !suppressSeconds || o.c.millisecond !== 0 || o.c.second !== 0, c3 = "";
11589
11599
  switch (precision) {
11590
11600
  case "day":
11591
11601
  case "month":
11592
11602
  case "year":
11593
11603
  break;
11594
11604
  default:
11595
- c2 += padStart(o.c.hour);
11605
+ c3 += padStart(o.c.hour);
11596
11606
  if (precision === "hour") break;
11597
11607
  if (extended) {
11598
- c2 += ":";
11599
- c2 += padStart(o.c.minute);
11608
+ c3 += ":";
11609
+ c3 += padStart(o.c.minute);
11600
11610
  if (precision === "minute") break;
11601
11611
  if (showSeconds) {
11602
- c2 += ":";
11603
- c2 += padStart(o.c.second);
11612
+ c3 += ":";
11613
+ c3 += padStart(o.c.second);
11604
11614
  }
11605
11615
  } else {
11606
- c2 += padStart(o.c.minute);
11616
+ c3 += padStart(o.c.minute);
11607
11617
  if (precision === "minute") break;
11608
11618
  if (showSeconds) {
11609
- c2 += padStart(o.c.second);
11619
+ c3 += padStart(o.c.second);
11610
11620
  }
11611
11621
  }
11612
11622
  if (precision === "second") break;
11613
11623
  if (showSeconds && (!suppressMilliseconds || o.c.millisecond !== 0)) {
11614
- c2 += ".";
11615
- c2 += padStart(o.c.millisecond, 3);
11624
+ c3 += ".";
11625
+ c3 += padStart(o.c.millisecond, 3);
11616
11626
  }
11617
11627
  }
11618
11628
  if (includeOffset) {
11619
11629
  if (o.isOffsetFixed && o.offset === 0 && !extendedZone) {
11620
- c2 += "Z";
11630
+ c3 += "Z";
11621
11631
  } else if (o.o < 0) {
11622
- c2 += "-";
11623
- c2 += padStart(Math.trunc(-o.o / 60));
11624
- c2 += ":";
11625
- c2 += padStart(Math.trunc(-o.o % 60));
11632
+ c3 += "-";
11633
+ c3 += padStart(Math.trunc(-o.o / 60));
11634
+ c3 += ":";
11635
+ c3 += padStart(Math.trunc(-o.o % 60));
11626
11636
  } else {
11627
- c2 += "+";
11628
- c2 += padStart(Math.trunc(o.o / 60));
11629
- c2 += ":";
11630
- c2 += padStart(Math.trunc(o.o % 60));
11637
+ c3 += "+";
11638
+ c3 += padStart(Math.trunc(o.o / 60));
11639
+ c3 += ":";
11640
+ c3 += padStart(Math.trunc(o.o % 60));
11631
11641
  }
11632
11642
  }
11633
11643
  if (extendedZone) {
11634
- c2 += "[" + o.zone.ianaName + "]";
11644
+ c3 += "[" + o.zone.ianaName + "]";
11635
11645
  }
11636
- return c2;
11646
+ return c3;
11637
11647
  }
11638
11648
  var defaultUnitValues = {
11639
11649
  month: 1,
@@ -11751,10 +11761,10 @@ var require_luxon = __commonJS({
11751
11761
  });
11752
11762
  }
11753
11763
  function diffRelative(start, end, opts) {
11754
- const round = isUndefined(opts.round) ? true : opts.round, rounding = isUndefined(opts.rounding) ? "trunc" : opts.rounding, format = (c2, unit) => {
11755
- c2 = roundTo(c2, round || opts.calendary ? 0 : 2, opts.calendary ? "round" : rounding);
11764
+ const round = isUndefined(opts.round) ? true : opts.round, rounding = isUndefined(opts.rounding) ? "trunc" : opts.rounding, format = (c3, unit) => {
11765
+ c3 = roundTo(c3, round || opts.calendary ? 0 : 2, opts.calendary ? "round" : rounding);
11756
11766
  const formatter = end.loc.clone(opts).relFormatter(opts);
11757
- return formatter.format(c2, unit);
11767
+ return formatter.format(c3, unit);
11758
11768
  }, differ = (unit) => {
11759
11769
  if (opts.calendary) {
11760
11770
  if (!end.hasSame(start, unit)) {
@@ -11795,16 +11805,16 @@ var require_luxon = __commonJS({
11795
11805
  const zone = config.zone || Settings.defaultZone;
11796
11806
  let invalid = config.invalid || (Number.isNaN(config.ts) ? new Invalid("invalid input") : null) || (!zone.isValid ? unsupportedZone(zone) : null);
11797
11807
  this.ts = isUndefined(config.ts) ? Settings.now() : config.ts;
11798
- let c2 = null, o = null;
11808
+ let c3 = null, o = null;
11799
11809
  if (!invalid) {
11800
11810
  const unchanged = config.old && config.old.ts === this.ts && config.old.zone.equals(zone);
11801
11811
  if (unchanged) {
11802
- [c2, o] = [config.old.c, config.old.o];
11812
+ [c3, o] = [config.old.c, config.old.o];
11803
11813
  } else {
11804
11814
  const ot = isNumber(config.o) && !config.old ? config.o : zone.offset(this.ts);
11805
- c2 = tsToObj(this.ts, ot);
11806
- invalid = Number.isNaN(c2.year) ? new Invalid("invalid input") : null;
11807
- c2 = invalid ? null : c2;
11815
+ c3 = tsToObj(this.ts, ot);
11816
+ invalid = Number.isNaN(c3.year) ? new Invalid("invalid input") : null;
11817
+ c3 = invalid ? null : c3;
11808
11818
  o = invalid ? null : ot;
11809
11819
  }
11810
11820
  }
@@ -11813,7 +11823,7 @@ var require_luxon = __commonJS({
11813
11823
  this.invalid = invalid;
11814
11824
  this.weekData = null;
11815
11825
  this.localWeekData = null;
11816
- this.c = c2;
11826
+ this.c = c3;
11817
11827
  this.o = o;
11818
11828
  this.isLuxonDateTime = true;
11819
11829
  }
@@ -12572,8 +12582,8 @@ var require_luxon = __commonJS({
12572
12582
  const ts1 = localTS - o1 * minuteMs;
12573
12583
  const ts2 = localTS - o2 * minuteMs;
12574
12584
  const c1 = tsToObj(ts1, o1);
12575
- const c2 = tsToObj(ts2, o2);
12576
- if (c1.hour === c2.hour && c1.minute === c2.minute && c1.second === c2.second && c1.millisecond === c2.millisecond) {
12585
+ const c22 = tsToObj(ts2, o2);
12586
+ if (c1.hour === c22.hour && c1.minute === c22.minute && c1.second === c22.second && c1.millisecond === c22.millisecond) {
12577
12587
  return [clone2(this, {
12578
12588
  ts: ts1
12579
12589
  }), clone2(this, {
@@ -12971,10 +12981,10 @@ var require_luxon = __commonJS({
12971
12981
  }
12972
12982
  precision = normalizeUnit(precision);
12973
12983
  const ext = format === "extended";
12974
- let c2 = toISODate(this, ext, precision);
12975
- if (orderedUnits.indexOf(precision) >= 3) c2 += "T";
12976
- c2 += toISOTime(this, ext, suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision);
12977
- return c2;
12984
+ let c3 = toISODate(this, ext, precision);
12985
+ if (orderedUnits.indexOf(precision) >= 3) c3 += "T";
12986
+ c3 += toISOTime(this, ext, suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision);
12987
+ return c3;
12978
12988
  }
12979
12989
  /**
12980
12990
  * Returns an ISO 8601-compliant string representation of this DateTime's date component
@@ -13033,8 +13043,8 @@ var require_luxon = __commonJS({
13033
13043
  return null;
13034
13044
  }
13035
13045
  precision = normalizeUnit(precision);
13036
- let c2 = includePrefix && orderedUnits.indexOf(precision) >= 3 ? "T" : "";
13037
- return c2 + toISOTime(this, format === "extended", suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision);
13046
+ let c3 = includePrefix && orderedUnits.indexOf(precision) >= 3 ? "T" : "";
13047
+ return c3 + toISOTime(this, format === "extended", suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision);
13038
13048
  }
13039
13049
  /**
13040
13050
  * Returns an RFC 2822-compatible string representation of this DateTime
@@ -17619,7 +17629,7 @@ attempted value: ${formattedValue}
17619
17629
  type: next.type,
17620
17630
  oneOf: next._whitelist.describe(),
17621
17631
  notOneOf: next._blacklist.describe(),
17622
- tests: next.tests.filter((n, idx, list) => list.findIndex((c2) => c2.OPTIONS.name === n.OPTIONS.name) === idx).map((fn) => {
17632
+ tests: next.tests.filter((n, idx, list) => list.findIndex((c3) => c3.OPTIONS.name === n.OPTIONS.name) === idx).map((fn) => {
17623
17633
  const params = fn.OPTIONS.params && options ? resolveParams(Object.assign({}, fn.OPTIONS.params), options) : fn.OPTIONS.params;
17624
17634
  return {
17625
17635
  name: fn.OPTIONS.name,
@@ -19867,6 +19877,7 @@ var require_utils = __commonJS({
19867
19877
  exports2.ALLOWED_PATCH_SYSTEM_FIELDS = exports2.getSystemAuthStatus = exports2.detectSystemAuthType = exports2.maskSystemCredentials = exports2.isSensitiveCredentialKey = exports2.ALLOWED_FILE_EXTENSIONS = exports2.getConnectionProtocol = void 0;
19868
19878
  exports2.validateExternalUrl = validateExternalUrl;
19869
19879
  exports2.flattenAndNamespaceCredentials = flattenAndNamespaceCredentials;
19880
+ exports2.flattenAndNamespaceSystemUrls = flattenAndNamespaceSystemUrls;
19870
19881
  exports2.generateUniqueId = generateUniqueId;
19871
19882
  exports2.waitForSystemProcessing = waitForSystemProcessing;
19872
19883
  exports2.inferJsonSchema = inferJsonSchema;
@@ -20067,6 +20078,14 @@ var require_utils = __commonJS({
20067
20078
  return acc;
20068
20079
  }, {});
20069
20080
  }
20081
+ function flattenAndNamespaceSystemUrls(systems2) {
20082
+ return systems2.reduce((acc, sys) => {
20083
+ if (sys.url) {
20084
+ acc[`${sys.id}_url`] = sys.url;
20085
+ }
20086
+ return acc;
20087
+ }, {});
20088
+ }
20070
20089
  async function generateUniqueId({ baseId, exists }) {
20071
20090
  if (!await exists(baseId)) {
20072
20091
  return baseId;
@@ -20448,6 +20467,7 @@ var require_utils = __commonJS({
20448
20467
  "multiTenancyMode",
20449
20468
  "documentationFiles",
20450
20469
  "tunnel"
20470
+ // Note: "environment" is NOT patchable because it's part of the composite primary key
20451
20471
  ];
20452
20472
  var SAMPLEABLE_KEYS = /* @__PURE__ */ new Set([
20453
20473
  "data",
@@ -21096,9 +21116,9 @@ var require_superglue_client = __commonJS({
21096
21116
  var types_js_1 = require_types();
21097
21117
  var sse_log_subscription_js_1 = require_sse_log_subscription();
21098
21118
  var SuperglueClient3 = class {
21099
- constructor({ endpoint, apiKey, apiEndpoint, onInfrastructureError }) {
21119
+ constructor({ apiKey, apiEndpoint, onInfrastructureError }) {
21100
21120
  this.apiKey = apiKey;
21101
- this.apiEndpoint = apiEndpoint ?? endpoint ?? "https://api.superglue.cloud";
21121
+ this.apiEndpoint = apiEndpoint ?? "https://api.superglue.cloud";
21102
21122
  this.sseManager = new sse_log_subscription_js_1.SSELogSubscriptionManager(this.apiEndpoint, this.apiKey);
21103
21123
  this.onInfrastructureError = onInfrastructureError;
21104
21124
  }
@@ -21218,14 +21238,16 @@ var require_superglue_client = __commonJS({
21218
21238
  * Execute a single step without creating a run in the database.
21219
21239
  * Used for individual step testing in the playground.
21220
21240
  */
21221
- async executeStep({ step, payload, previousResults, credentials, options, runId }) {
21241
+ async executeStep({ step, payload, previousResults, credentials, options, runId, mode, systemIds }) {
21222
21242
  return this.restRequest("POST", "/v1/tools/step/run", {
21223
21243
  step,
21224
21244
  payload,
21225
21245
  previousResults,
21226
21246
  credentials,
21227
21247
  options,
21228
- runId
21248
+ runId,
21249
+ mode,
21250
+ systemIds
21229
21251
  });
21230
21252
  }
21231
21253
  /**
@@ -21400,11 +21422,14 @@ var require_superglue_client = __commonJS({
21400
21422
  newId
21401
21423
  });
21402
21424
  }
21403
- async listSystems(limit = 10, page = 1) {
21425
+ async listSystems(limit = 10, page = 1, options) {
21404
21426
  const params = new URLSearchParams({
21405
21427
  limit: String(limit),
21406
21428
  page: String(page)
21407
21429
  });
21430
+ if (options?.mode) {
21431
+ params.set("mode", options.mode);
21432
+ }
21408
21433
  const response = await this.restRequest("GET", `/v1/systems?${params.toString()}`);
21409
21434
  return { items: response.data, total: response.total };
21410
21435
  }
@@ -21413,20 +21438,23 @@ var require_superglue_client = __commonJS({
21413
21438
  const response = await this.restRequest("GET", `/v1/tools/search${params}`);
21414
21439
  return response.data;
21415
21440
  }
21416
- async getSystem(id) {
21417
- const response = await this.restRequest("GET", `/v1/systems/${encodeURIComponent(id)}`);
21441
+ async getSystem(id, options) {
21442
+ const queryParams = options?.environment ? `?env=${options.environment}` : "";
21443
+ const response = await this.restRequest("GET", `/v1/systems/${encodeURIComponent(id)}${queryParams}`);
21418
21444
  return response.data;
21419
21445
  }
21420
21446
  async createSystem(input) {
21421
21447
  const response = await this.restRequest("POST", "/v1/systems", input);
21422
21448
  return response.data;
21423
21449
  }
21424
- async updateSystem(id, input) {
21425
- const response = await this.restRequest("PATCH", `/v1/systems/${encodeURIComponent(id)}`, input);
21450
+ async updateSystem(id, input, options) {
21451
+ const queryParams = options?.environment ? `?env=${options.environment}` : "";
21452
+ const response = await this.restRequest("PATCH", `/v1/systems/${encodeURIComponent(id)}${queryParams}`, input);
21426
21453
  return response.data;
21427
21454
  }
21428
- async deleteSystem(id) {
21429
- await this.restRequest("DELETE", `/v1/systems/${encodeURIComponent(id)}`);
21455
+ async deleteSystem(id, options) {
21456
+ const queryParams = options?.environment ? `?env=${options.environment}` : "";
21457
+ await this.restRequest("DELETE", `/v1/systems/${encodeURIComponent(id)}${queryParams}`);
21430
21458
  return true;
21431
21459
  }
21432
21460
  async cacheOAuthSecret(args) {
@@ -21584,18 +21612,14 @@ var require_dist2 = __commonJS({
21584
21612
  });
21585
21613
 
21586
21614
  // src/cli.ts
21587
- var import_commander = require("commander");
21615
+ var import_commander5 = require("commander");
21588
21616
 
21589
21617
  // src/config.ts
21590
21618
  var fs = __toESM(require("fs"));
21591
21619
  var os = __toESM(require("os"));
21592
21620
  var path = __toESM(require("path"));
21593
21621
  var DEFAULT_CONFIG = {
21594
- output: { mode: "stdout", directory: ".superglue/output" },
21595
- policies: {
21596
- callSystem: "ask_every_time",
21597
- editTool: "confirm"
21598
- }
21622
+ output: { mode: "stdout", directory: ".superglue/output" }
21599
21623
  };
21600
21624
  function getConfigDir(preferLocal) {
21601
21625
  const localDir = path.join(process.cwd(), ".superglue");
@@ -21638,8 +21662,7 @@ function resolveConfig(flags) {
21638
21662
  apiKey,
21639
21663
  endpoint,
21640
21664
  webEndpoint,
21641
- output: { ...DEFAULT_CONFIG.output, ...file.output },
21642
- policies: { ...DEFAULT_CONFIG.policies, ...file.policies }
21665
+ output: { ...DEFAULT_CONFIG.output, ...file.output }
21643
21666
  };
21644
21667
  }
21645
21668
  function writeConfig(config, preferLocal) {
@@ -21692,9 +21715,10 @@ var package_default = {
21692
21715
  sg: "./dist/cli.js"
21693
21716
  },
21694
21717
  files: [
21718
+ ".claude-plugin/",
21695
21719
  "dist/",
21696
21720
  "skills/",
21697
- "skills.md"
21721
+ "LICENSE"
21698
21722
  ],
21699
21723
  dependencies: {
21700
21724
  commander: "^13.0.0",
@@ -21820,6 +21844,10 @@ var c = {
21820
21844
  bgMagenta: "\x1B[45m",
21821
21845
  bgCyan: "\x1B[46m"
21822
21846
  };
21847
+ function link(url, label) {
21848
+ const text = label || url;
21849
+ return `\x1B]8;;${url}\x07${c.underline}${c.cyan}${text}${c.reset}\x1B]8;;\x07`;
21850
+ }
21823
21851
  function banner() {
21824
21852
  if (isJsonMode()) return;
21825
21853
  const rst = c.reset;
@@ -21856,20 +21884,28 @@ function banner() {
21856
21884
  function spinner(message) {
21857
21885
  if (isJsonMode()) return { stop: () => {
21858
21886
  }, update: () => {
21887
+ }, log: () => {
21859
21888
  } };
21860
21889
  const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
21861
21890
  let i = 0;
21862
21891
  let currentMsg = message;
21863
- const interval = setInterval(() => {
21892
+ const clearLine = () => process.stdout.write(`\r\x1B[2K`);
21893
+ const drawSpinner = () => {
21864
21894
  process.stdout.write(`\r ${c.cyan}${frames[i++ % frames.length]}${c.reset} ${currentMsg}`);
21865
- }, 80);
21895
+ };
21896
+ const interval = setInterval(drawSpinner, 80);
21866
21897
  return {
21867
21898
  update: (msg) => {
21868
21899
  currentMsg = msg;
21869
21900
  },
21901
+ log: (line) => {
21902
+ clearLine();
21903
+ console.log(` ${c.dim}\u2502${c.reset} ${line}`);
21904
+ drawSpinner();
21905
+ },
21870
21906
  stop: (finalMsg) => {
21871
21907
  clearInterval(interval);
21872
- process.stdout.write(`\r${"".padEnd(currentMsg.length + 10)}\r`);
21908
+ clearLine();
21873
21909
  if (finalMsg) console.log(` ${finalMsg}`);
21874
21910
  }
21875
21911
  };
@@ -22070,16 +22106,6 @@ function renderDiffs(diffs) {
22070
22106
  return ` ${color}${icon} ${c.bold}[${d.op}]${c.reset} ${c.dim}${d.path}${c.reset}${valueStr}`;
22071
22107
  }).join("\n");
22072
22108
  }
22073
- async function confirm(message) {
22074
- if (process.argv.includes("--yes") || process.argv.includes("-y")) return true;
22075
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
22076
- return new Promise((resolve4) => {
22077
- rl.question(` ${message} ${c.dim}[y/N]${c.reset} `, (answer) => {
22078
- rl.close();
22079
- resolve4(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
22080
- });
22081
- });
22082
- }
22083
22109
  async function prompt(message, defaultValue) {
22084
22110
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
22085
22111
  const suffix = defaultValue ? ` ${c.dim}[${defaultValue}]${c.reset}` : "";
@@ -22092,23 +22118,30 @@ async function prompt(message, defaultValue) {
22092
22118
  }
22093
22119
  async function promptHidden(message) {
22094
22120
  return new Promise((resolve4) => {
22095
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
22096
- process.stdout.write(` ${message}: `);
22097
- if (process.stdin.isTTY) {
22098
- process.stdin.setRawMode(true);
22121
+ process.stdout.write(`${message}: `);
22122
+ if (!process.stdin.isTTY) {
22123
+ const rl = readline.createInterface({ input: process.stdin });
22124
+ rl.once("line", (line) => {
22125
+ rl.close();
22126
+ resolve4(line.trim());
22127
+ });
22128
+ return;
22099
22129
  }
22130
+ process.stdin.setRawMode(true);
22131
+ process.stdin.resume();
22100
22132
  let input = "";
22101
22133
  const onData = (ch) => {
22102
22134
  const s = ch.toString();
22103
22135
  for (const char of s) {
22104
22136
  if (char === "\n" || char === "\r") {
22105
- if (process.stdin.isTTY) process.stdin.setRawMode(false);
22137
+ process.stdin.setRawMode(false);
22106
22138
  process.stdin.removeListener("data", onData);
22139
+ process.stdin.pause();
22107
22140
  process.stdout.write("\n");
22108
- rl.close();
22109
22141
  resolve4(input);
22110
22142
  return;
22111
22143
  } else if (char === "") {
22144
+ process.stdin.setRawMode(false);
22112
22145
  process.exit(130);
22113
22146
  } else if (char === "\x7F" || char === "\b") {
22114
22147
  if (input.length > 0) {
@@ -22122,20 +22155,60 @@ async function promptHidden(message) {
22122
22155
  }
22123
22156
  };
22124
22157
  process.stdin.on("data", onData);
22125
- process.stdin.resume();
22126
22158
  });
22127
22159
  }
22128
22160
  async function choose(message, options, defaultIndex = 0) {
22129
22161
  if (!process.stdout.isTTY) return defaultIndex;
22130
- console.log("");
22131
- for (let i = 0; i < options.length; i++) {
22132
- const marker = i === defaultIndex ? `${c.cyan}\u276F${c.reset}` : " ";
22133
- const label = i === defaultIndex ? `${c.bold}${options[i]}${c.reset}` : `${c.dim}${options[i]}${c.reset}`;
22134
- console.log(` ${marker} ${c.dim}(${i + 1})${c.reset} ${label}`);
22135
- }
22136
- const answer = await prompt(` ${message}`, String(defaultIndex + 1));
22137
- const idx = parseInt(answer, 10) - 1;
22138
- return idx >= 0 && idx < options.length ? idx : defaultIndex;
22162
+ let selected = defaultIndex;
22163
+ const render = () => {
22164
+ for (let i = 0; i < options.length; i++) {
22165
+ const marker = i === selected ? `${c.cyan}\u276F${c.reset}` : " ";
22166
+ const label = i === selected ? `${c.bold}${options[i]}${c.reset}` : `${c.dim}${options[i]}${c.reset}`;
22167
+ console.log(` ${marker} ${label}`);
22168
+ }
22169
+ };
22170
+ const moveUp = () => {
22171
+ process.stdout.write(`\x1B[${options.length}A\r`);
22172
+ for (let i = 0; i < options.length; i++) {
22173
+ process.stdout.write(`\x1B[2K`);
22174
+ if (i < options.length - 1) process.stdout.write(`
22175
+ `);
22176
+ }
22177
+ process.stdout.write(`\x1B[${options.length - 1}A\r`);
22178
+ };
22179
+ console.log(
22180
+ `
22181
+ ${c.bold}${message}${c.reset} ${c.dim}(\u2191/\u2193 to select, enter to confirm)${c.reset}`
22182
+ );
22183
+ render();
22184
+ return new Promise((resolve4) => {
22185
+ process.stdin.setRawMode(true);
22186
+ process.stdin.resume();
22187
+ const onData = (ch) => {
22188
+ const s = ch.toString();
22189
+ if (s === "\r" || s === "\n") {
22190
+ process.stdin.setRawMode(false);
22191
+ process.stdin.removeListener("data", onData);
22192
+ process.stdin.pause();
22193
+ resolve4(selected);
22194
+ return;
22195
+ }
22196
+ if (s === "") {
22197
+ process.stdin.setRawMode(false);
22198
+ process.exit(130);
22199
+ }
22200
+ if (s === "\x1B[A" || s === "k") {
22201
+ selected = (selected - 1 + options.length) % options.length;
22202
+ } else if (s === "\x1B[B" || s === "j") {
22203
+ selected = (selected + 1) % options.length;
22204
+ } else {
22205
+ return;
22206
+ }
22207
+ moveUp();
22208
+ render();
22209
+ };
22210
+ process.stdin.on("data", onData);
22211
+ });
22139
22212
  }
22140
22213
 
22141
22214
  // src/commands/init.ts
@@ -22146,6 +22219,10 @@ function registerInitCommand(program2) {
22146
22219
  console.log(` ${c.dim}Let's get you connected in a few steps.${c.reset}
22147
22220
  `);
22148
22221
  heading("Authentication");
22222
+ console.log(
22223
+ ` ${c.dim}Get your API key at${c.reset} ${link("https://app.superglue.cloud/admin?view=api-keys")}`
22224
+ );
22225
+ console.log("");
22149
22226
  const apiKey = await promptHidden(" API Key");
22150
22227
  if (!apiKey) {
22151
22228
  error("API key is required");
@@ -22178,25 +22255,6 @@ function registerInitCommand(program2) {
22178
22255
  if (outputMode === "stdout+file") {
22179
22256
  outputDir = await prompt(" Output directory", ".superglue/output");
22180
22257
  }
22181
- heading("Execution Policies");
22182
- console.log(` ${c.dim}These control when the CLI asks for confirmation.${c.reset}
22183
- `);
22184
- const callPolicyIdx = await choose(
22185
- "API call confirmation",
22186
- ["Ask every time", "Auto-run GET requests only", "Auto-run everything"],
22187
- 0
22188
- );
22189
- const callPolicies = [
22190
- "ask_every_time",
22191
- "run_gets_only",
22192
- "run_everything"
22193
- ];
22194
- const editPolicyIdx = await choose(
22195
- "Tool edit confirmation",
22196
- ["Show diff and ask to confirm", "Auto-accept all changes"],
22197
- 0
22198
- );
22199
- const editPolicies = ["confirm", "auto_accept"];
22200
22258
  heading("Config Location");
22201
22259
  const homeDir = os2.homedir();
22202
22260
  const localPath = path2.join(process.cwd(), ".superglue");
@@ -22214,11 +22272,7 @@ function registerInitCommand(program2) {
22214
22272
  apiKey,
22215
22273
  endpoint,
22216
22274
  webEndpoint,
22217
- output: { mode: outputMode, directory: outputDir },
22218
- policies: {
22219
- callSystem: callPolicies[callPolicyIdx],
22220
- editTool: editPolicies[editPolicyIdx]
22221
- }
22275
+ output: { mode: outputMode, directory: outputDir }
22222
22276
  };
22223
22277
  writeConfig(config, preferLocal);
22224
22278
  ensureConfigDirs(config, preferLocal);
@@ -22449,8 +22503,10 @@ function registerBuildCommand(parent, getContext2) {
22449
22503
  // src/commands/tool/run.ts
22450
22504
  var fs6 = __toESM(require("fs"));
22451
22505
  var path5 = __toESM(require("path"));
22506
+ var crypto2 = __toESM(require("crypto"));
22507
+ var import_shared4 = __toESM(require_dist2());
22452
22508
  function registerRunCommand(parent, getContext2) {
22453
- parent.command("run").description("Execute a draft or saved tool").option("--draft <id>", "Draft ID from build").option("--tool <id>", "Saved tool ID").option("--payload <json>", "JSON payload").option("--payload-file <path>", "JSON payload file").option(
22509
+ parent.command("run").description("Execute a draft, saved tool, or inline tool config").option("--draft <id>", "Draft ID from build").option("--tool <id>", "Saved tool ID").option("--config <json>", "Inline tool config JSON").option("--config-file <path>", "Tool config JSON file").option("--payload <json>", "JSON payload").option("--payload-file <path>", "JSON payload file").option(
22454
22510
  "--file <key=path...>",
22455
22511
  "File references",
22456
22512
  (v, arr) => {
@@ -22460,8 +22516,13 @@ function registerRunCommand(parent, getContext2) {
22460
22516
  []
22461
22517
  ).option("--include-step-results", "Include raw step results").option("--include-config", "Include full tool config").action(async (opts) => {
22462
22518
  const { config, client } = getContext2();
22463
- if (!opts.draft && !opts.tool) {
22464
- error("Provide --draft or --tool");
22519
+ const selectors = [opts.tool, opts.draft, opts.config, opts.configFile].filter(Boolean);
22520
+ if (selectors.length === 0) {
22521
+ error("Provide one of --tool, --draft, --config, or --config-file");
22522
+ process.exit(1);
22523
+ }
22524
+ if (selectors.length > 1) {
22525
+ error("Only one of --tool, --draft, --config, or --config-file can be used");
22465
22526
  process.exit(1);
22466
22527
  }
22467
22528
  const filePayloads = await parseFileFlags(opts.file, client);
@@ -22475,32 +22536,67 @@ function registerRunCommand(parent, getContext2) {
22475
22536
  payload = fileResult.resolved;
22476
22537
  }
22477
22538
  let result;
22478
- const toolLabel = opts.tool || opts.draft;
22539
+ const toolLabel = opts.tool || opts.draft || "inline-config";
22540
+ const traceId = crypto2.randomUUID();
22479
22541
  const spin = spinner(`Running ${c.bold}${toolLabel}${c.reset}...`);
22480
- if (opts.tool) {
22542
+ const logSub = await client.subscribeToLogsSSE({
22543
+ traceId,
22544
+ onLog: (log) => spin.log(`${c.dim}${log.message}${c.reset}`)
22545
+ }).catch(() => ({ unsubscribe: () => {
22546
+ } }));
22547
+ const runToolConfig = async (toolConfig) => {
22481
22548
  try {
22482
- result = await client.runTool({ toolId: opts.tool, payload });
22549
+ const res = await client.runToolConfig({
22550
+ tool: toolConfig,
22551
+ payload,
22552
+ options: { requestSource: import_shared4.RequestSource.CLI },
22553
+ traceId
22554
+ });
22555
+ logSub.unsubscribe();
22483
22556
  spin.stop();
22557
+ return res;
22484
22558
  } catch (err) {
22559
+ logSub.unsubscribe();
22485
22560
  spin.stop();
22486
22561
  error(err.message);
22487
22562
  process.exit(1);
22488
22563
  }
22489
- } else {
22490
- const draft = readDraft(opts.draft);
22491
- if (!draft) {
22564
+ };
22565
+ if (opts.tool) {
22566
+ try {
22567
+ result = await client.runTool({
22568
+ toolId: opts.tool,
22569
+ payload,
22570
+ options: { requestSource: import_shared4.RequestSource.CLI, traceId }
22571
+ });
22572
+ logSub.unsubscribe();
22492
22573
  spin.stop();
22493
- error(`Draft not found: ${opts.draft}`);
22574
+ } catch (err) {
22575
+ logSub.unsubscribe();
22576
+ spin.stop();
22577
+ error(err.message);
22494
22578
  process.exit(1);
22495
22579
  }
22580
+ } else if (opts.config || opts.configFile) {
22581
+ let toolConfig;
22496
22582
  try {
22497
- result = await client.runToolConfig({ tool: draft.config, payload });
22498
- spin.stop();
22583
+ toolConfig = opts.configFile ? JSON.parse(fs6.readFileSync(opts.configFile, "utf-8")) : JSON.parse(opts.config);
22499
22584
  } catch (err) {
22585
+ logSub.unsubscribe();
22500
22586
  spin.stop();
22501
- error(err.message);
22587
+ error(`Invalid tool config JSON: ${err.message}`);
22588
+ process.exit(1);
22589
+ }
22590
+ result = await runToolConfig(toolConfig);
22591
+ } else {
22592
+ const draft = readDraft(opts.draft);
22593
+ if (!draft) {
22594
+ logSub.unsubscribe();
22595
+ spin.stop();
22596
+ error(`Draft not found: ${opts.draft}`);
22502
22597
  process.exit(1);
22503
22598
  }
22599
+ result = await runToolConfig(draft.config);
22504
22600
  }
22505
22601
  const out = {
22506
22602
  success: result.success,
@@ -22513,7 +22609,7 @@ function registerRunCommand(parent, getContext2) {
22513
22609
  if (config.output.mode === "stdout+file") {
22514
22610
  const outDir = path5.resolve(config.output.directory);
22515
22611
  if (!fs6.existsSync(outDir)) fs6.mkdirSync(outDir, { recursive: true });
22516
- const rawId = opts.tool || opts.draft;
22612
+ const rawId = opts.tool || opts.draft || "inline-config";
22517
22613
  const safeId = path5.basename(rawId).replace(/[^a-zA-Z0-9_-]/g, "_");
22518
22614
  const filename = `${safeId}-${Date.now()}.json`;
22519
22615
  fs6.writeFileSync(path5.join(outDir, filename), JSON.stringify(out, null, 2));
@@ -22524,11 +22620,11 @@ function registerRunCommand(parent, getContext2) {
22524
22620
 
22525
22621
  // src/commands/tool/edit.ts
22526
22622
  var fs7 = __toESM(require("fs"));
22527
- var import_shared4 = __toESM(require_dist2());
22623
+ var import_shared5 = __toESM(require_dist2());
22528
22624
  var jsonpatch = __toESM(require("fast-json-patch"));
22529
22625
  function registerEditCommand(parent, getContext2) {
22530
- parent.command("edit").description("Edit a tool using JSON Patch operations").option("--draft <id>", "Draft ID to edit").option("--tool <id>", "Saved tool ID to edit").option("--patches <json-or-file>", "JSON Patch array (inline JSON or file path)").option("--payload <json>", "Test payload JSON").option("--test", "Run the patched tool after accepting").action(async (opts) => {
22531
- const { config, client } = getContext2();
22626
+ parent.command("edit").description("Edit a tool using JSON Patch operations").option("--draft <id>", "Draft ID to edit").option("--tool <id>", "Saved tool ID to edit").option("--patches <json-or-file>", "JSON Patch array (inline JSON or file path)").action(async (opts) => {
22627
+ const { client } = getContext2();
22532
22628
  if (!opts.draft && !opts.tool) {
22533
22629
  error("Provide --draft or --tool");
22534
22630
  process.exit(1);
@@ -22574,7 +22670,7 @@ function registerEditCommand(parent, getContext2) {
22574
22670
  try {
22575
22671
  const copy = JSON.parse(JSON.stringify(originalConfig));
22576
22672
  const result = jsonpatch.applyPatch(copy, patches, true, true);
22577
- patchedConfig = (0, import_shared4.normalizeToolSchemas)(result.newDocument || copy);
22673
+ patchedConfig = (0, import_shared5.normalizeToolSchemas)(result.newDocument || copy);
22578
22674
  } catch (err) {
22579
22675
  error(`Patch failed: ${err.message}`);
22580
22676
  process.exit(1);
@@ -22590,14 +22686,6 @@ function registerEditCommand(parent, getContext2) {
22590
22686
  console.log(renderDiffs(diffs));
22591
22687
  console.log("");
22592
22688
  }
22593
- const autoAccept = process.argv.includes("--yes") || process.argv.includes("-y") || config.policies.editTool === "auto_accept";
22594
- if (!autoAccept) {
22595
- const accepted = await confirm("Accept changes?");
22596
- if (!accepted) {
22597
- output({ success: false, rejected: true, message: "Changes rejected" });
22598
- process.exit(1);
22599
- }
22600
- }
22601
22689
  const draft = {
22602
22690
  draftId: workingDraftId,
22603
22691
  config: {
@@ -22610,54 +22698,11 @@ function registerEditCommand(parent, getContext2) {
22610
22698
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
22611
22699
  };
22612
22700
  writeDraft(draft);
22613
- if (opts.test) {
22614
- let payload;
22615
- try {
22616
- payload = opts.payload ? JSON.parse(opts.payload) : {};
22617
- } catch (err) {
22618
- error(`Invalid --payload JSON: ${err.message}`);
22619
- process.exit(1);
22620
- }
22621
- const spin = spinner("Running test...");
22622
- try {
22623
- const testResult = await client.runToolConfig({ tool: draft.config, payload });
22624
- spin.stop();
22625
- if (testResult.success) {
22626
- success("Test passed");
22627
- } else {
22628
- error(`Test failed: ${testResult.error || "Unknown error"}`);
22629
- }
22630
- if (process.argv.includes("--json") || !process.stdout.isTTY) {
22631
- output({
22632
- success: true,
22633
- draftId: workingDraftId,
22634
- diffs,
22635
- testResult: {
22636
- success: testResult.success,
22637
- data: testResult.data,
22638
- error: testResult.error
22639
- }
22640
- });
22641
- } else {
22642
- output(testResult.data);
22643
- }
22644
- } catch (err) {
22645
- spin.stop();
22646
- error(`Test error: ${err.message}`);
22647
- output({
22648
- success: true,
22649
- draftId: workingDraftId,
22650
- diffs,
22651
- testResult: { success: false, error: err.message }
22652
- });
22653
- }
22701
+ if (process.argv.includes("--json") || !process.stdout.isTTY) {
22702
+ output({ success: true, draftId: workingDraftId, diffs });
22654
22703
  } else {
22655
- if (process.argv.includes("--json") || !process.stdout.isTTY) {
22656
- output({ success: true, draftId: workingDraftId, diffs });
22657
- } else {
22658
- success(`Draft updated: ${c.bold}${workingDraftId}${c.reset}`);
22659
- console.log("");
22660
- }
22704
+ success(`Draft updated: ${c.bold}${workingDraftId}${c.reset}`);
22705
+ console.log("");
22661
22706
  }
22662
22707
  });
22663
22708
  }
@@ -22773,7 +22818,8 @@ function registerToolCommands(program2, getContext2) {
22773
22818
 
22774
22819
  // src/commands/system/create.ts
22775
22820
  var fs8 = __toESM(require("fs"));
22776
- var import_shared5 = __toESM(require_dist2());
22821
+ var import_commander = require("commander");
22822
+ var import_shared6 = __toESM(require_dist2());
22777
22823
  async function collectSensitiveCredentials(fields) {
22778
22824
  const creds = {};
22779
22825
  for (const field of fields) {
@@ -22791,12 +22837,21 @@ async function collectSensitiveCredentials(fields) {
22791
22837
  return creds;
22792
22838
  }
22793
22839
  function registerCreateCommand(parent, getContext2) {
22794
- parent.command("create").description("Create a new system").option("--config <file>", "JSON config file").option("--id <id>", "System ID").option("--name <name>", "Human-readable name").option("--url <url>", "API URL").option("--template <id>", "Template ID").option("--instructions <text>", "Specific instructions").option("--credentials <json>", "Non-sensitive credentials JSON").option("--sensitive-credentials <fields>", "Comma-separated sensitive credential field names").option("--docs-url <url>", "Documentation URL to scrape").option("--openapi-url <url>", "OpenAPI spec URL").action(async (opts) => {
22840
+ parent.command("create").description("Create a new system").option("--config <file>", "JSON config file").option("--id <id>", "System ID").option("--name <name>", "Human-readable name").option("--url <url>", "API URL").option("--template <id>", "Template ID").option("--instructions <text>", "Specific instructions").option("--credentials <json>", "Non-sensitive credentials JSON").option("--sensitive-credentials <fields>", "Comma-separated sensitive credential field names").option("--docs-url <url>", "Documentation URL to scrape").option("--openapi-url <url>", "OpenAPI spec URL").addOption(
22841
+ new import_commander.Option("--env <environment>", "Environment: dev or prod (default: prod)").choices([
22842
+ "dev",
22843
+ "prod"
22844
+ ])
22845
+ ).action(async (opts) => {
22795
22846
  const { client } = getContext2();
22796
22847
  let systemInput;
22797
22848
  if (opts.config) {
22798
22849
  try {
22799
- systemInput = JSON.parse(fs8.readFileSync(opts.config, "utf-8"));
22850
+ const parsed = JSON.parse(fs8.readFileSync(opts.config, "utf-8"));
22851
+ if (opts.env === "dev" || opts.env === "prod") {
22852
+ parsed.environment = opts.env;
22853
+ }
22854
+ systemInput = parsed;
22800
22855
  } catch (err) {
22801
22856
  error(`Invalid config file: ${err.message}`);
22802
22857
  process.exit(1);
@@ -22816,14 +22871,15 @@ function registerCreateCommand(parent, getContext2) {
22816
22871
  name: opts.name,
22817
22872
  url: opts.url,
22818
22873
  specificInstructions: opts.instructions,
22819
- credentials
22874
+ credentials,
22875
+ environment: opts.env === "dev" || opts.env === "prod" ? opts.env : void 0
22820
22876
  };
22821
22877
  }
22822
22878
  if (opts.template) {
22823
- const template = import_shared5.systems[opts.template];
22879
+ const template = import_shared6.systems[opts.template];
22824
22880
  if (!template) {
22825
22881
  error(
22826
- `Template not found: ${opts.template}. Available: ${Object.keys(import_shared5.systems).join(", ")}`
22882
+ `Template not found: ${opts.template}. Available: ${Object.keys(import_shared6.systems).join(", ")}`
22827
22883
  );
22828
22884
  process.exit(1);
22829
22885
  }
@@ -22886,8 +22942,11 @@ function registerCreateCommand(parent, getContext2) {
22886
22942
  }
22887
22943
 
22888
22944
  // src/commands/system/edit.ts
22945
+ var import_commander2 = require("commander");
22889
22946
  function registerEditCommand2(parent, getContext2) {
22890
- parent.command("edit").description("Edit an existing system").requiredOption("--id <id>", "System ID").option("--name <name>", "New name").option("--url <url>", "New URL").option("--instructions <text>", "New specific instructions").option("--credentials <json>", "Non-sensitive credentials JSON to merge").option("--sensitive-credentials <fields>", "Comma-separated sensitive credential field names").option("--scrape-url <url>", "Documentation URL to scrape").option("--scrape-keywords <keywords>", "Space-separated scrape keywords").action(async (opts) => {
22947
+ parent.command("edit").description("Edit an existing system").requiredOption("--id <id>", "System ID").option("--name <name>", "New name").option("--url <url>", "New URL").option("--instructions <text>", "New specific instructions").option("--credentials <json>", "Non-sensitive credentials JSON to merge").option("--sensitive-credentials <fields>", "Comma-separated sensitive credential field names").option("--scrape-url <url>", "Documentation URL to scrape").option("--scrape-keywords <keywords>", "Space-separated scrape keywords").addOption(
22948
+ new import_commander2.Option("--env <environment>", "Environment: dev or prod").choices(["dev", "prod"])
22949
+ ).action(async (opts) => {
22891
22950
  const { client } = getContext2();
22892
22951
  const patchPayload = { id: opts.id };
22893
22952
  if (opts.name) patchPayload.name = opts.name;
@@ -22919,8 +22978,9 @@ function registerEditCommand2(parent, getContext2) {
22919
22978
  patchPayload.credentials = { ...patchPayload.credentials, ...creds };
22920
22979
  }
22921
22980
  try {
22981
+ const envOption = opts.env === "dev" || opts.env === "prod" ? { environment: opts.env } : void 0;
22922
22982
  const spin = spinner(`Updating system ${c.bold}${opts.id}${c.reset}...`);
22923
- const existing = await client.getSystem(opts.id);
22983
+ const existing = await client.getSystem(opts.id, envOption);
22924
22984
  if (!existing) {
22925
22985
  spin.stop();
22926
22986
  error(`System not found: ${opts.id}`);
@@ -22929,7 +22989,7 @@ function registerEditCommand2(parent, getContext2) {
22929
22989
  if (patchPayload.credentials && existing.credentials) {
22930
22990
  patchPayload.credentials = { ...existing.credentials, ...patchPayload.credentials };
22931
22991
  }
22932
- const result = await client.updateSystem(opts.id, patchPayload);
22992
+ const result = await client.updateSystem(opts.id, patchPayload, envOption);
22933
22993
  if (opts.scrapeUrl) {
22934
22994
  try {
22935
22995
  const keywords = opts.scrapeKeywords?.split(" ").filter(Boolean);
@@ -22956,45 +23016,52 @@ function registerEditCommand2(parent, getContext2) {
22956
23016
  }
22957
23017
 
22958
23018
  // src/commands/system/find.ts
22959
- var import_shared6 = __toESM(require_dist2());
23019
+ var import_commander3 = require("commander");
23020
+ var import_shared7 = __toESM(require_dist2());
22960
23021
  function filterSystemFields(system) {
22961
23022
  const credentialKeys = Object.keys(system.credentials || {});
22962
23023
  return {
22963
23024
  id: system.id,
22964
23025
  name: system.name,
22965
23026
  url: system.url,
23027
+ environment: system.environment,
22966
23028
  specificInstructions: system.specificInstructions,
22967
23029
  credentialPlaceholders: credentialKeys.map((k) => `<<${system.id}_${k}>>`)
22968
23030
  };
22969
23031
  }
22970
23032
  function registerFindCommand2(parent, getContext2) {
22971
- parent.command("list").description("List all systems").action(async () => {
23033
+ parent.command("list").description("List all systems").option("--mode <mode>", "Filter by environment: dev, prod, or all (default: all)").action(async (opts) => {
22972
23034
  const { client } = getContext2();
22973
23035
  try {
22974
- const { items } = await client.listSystems(100);
23036
+ const mode = opts.mode === "dev" || opts.mode === "prod" ? opts.mode : "all";
23037
+ const { items } = await client.listSystems(100, 1, { mode });
22975
23038
  table(
22976
23039
  items.map((s) => ({
22977
23040
  id: s.id,
22978
23041
  name: s.name || "",
23042
+ env: s.environment || "prod",
22979
23043
  url: (s.url || "").slice(0, 50)
22980
23044
  })),
22981
- ["id", "name", "url"]
23045
+ ["id", "name", "env", "url"]
22982
23046
  );
22983
23047
  } catch (err) {
22984
23048
  error(err.message);
22985
23049
  process.exit(1);
22986
23050
  }
22987
23051
  });
22988
- parent.command("find [query]").description("Find systems by query or exact ID").option("--id <exactId>", "Exact system ID lookup").action(async (query, opts) => {
23052
+ parent.command("find [query]").description("Find systems by query or exact ID").option("--id <exactId>", "Exact system ID lookup").addOption(
23053
+ new import_commander3.Option("--env <environment>", "Environment: dev or prod").choices(["dev", "prod"])
23054
+ ).action(async (query, opts) => {
22989
23055
  const { client } = getContext2();
22990
23056
  try {
22991
23057
  if (opts.id) {
22992
- const system = await client.getSystem(opts.id);
23058
+ const envOption = opts.env === "dev" || opts.env === "prod" ? { environment: opts.env } : void 0;
23059
+ const system = await client.getSystem(opts.id, envOption);
22993
23060
  if (!system) {
22994
23061
  error(`System not found: ${opts.id}`);
22995
23062
  process.exit(1);
22996
23063
  }
22997
- const templateMatch = (0, import_shared6.findTemplateForSystem)(system);
23064
+ const templateMatch = (0, import_shared7.findTemplateForSystem)(system);
22998
23065
  output({
22999
23066
  success: true,
23000
23067
  system: filterSystemFields(system),
@@ -23002,8 +23069,9 @@ function registerFindCommand2(parent, getContext2) {
23002
23069
  });
23003
23070
  return;
23004
23071
  }
23072
+ const listMode = opts.env ? { mode: opts.env } : void 0;
23005
23073
  const rawQuery = (query || "*").trim();
23006
- const { items } = await client.listSystems(100);
23074
+ const { items } = await client.listSystems(100, 1, listMode);
23007
23075
  if (rawQuery === "*") {
23008
23076
  output({
23009
23077
  success: true,
@@ -23028,16 +23096,8 @@ function registerFindCommand2(parent, getContext2) {
23028
23096
  }
23029
23097
 
23030
23098
  // src/commands/system/call.ts
23031
- var import_shared7 = __toESM(require_dist2());
23032
- function shouldAutoExecute(policy, method, url) {
23033
- if (policy === "run_everything") return true;
23034
- if (policy === "ask_every_time") return false;
23035
- if (policy === "run_gets_only") {
23036
- const protocol = (0, import_shared7.getConnectionProtocol)(url);
23037
- return protocol === "http" && method.toUpperCase() === "GET";
23038
- }
23039
- return false;
23040
- }
23099
+ var import_commander4 = require("commander");
23100
+ var import_shared8 = __toESM(require_dist2());
23041
23101
  function registerCallCommand(parent, getContext2) {
23042
23102
  parent.command("call").description("Call a system (API, database, file server)").requiredOption("--url <url>", "Full URL including protocol").option("--system-id <id>", "System ID for credential injection").option("--method <method>", "HTTP method", "GET").option("--headers <json>", "HTTP headers JSON").option("--body <string>", "Request body").option(
23043
23103
  "--file <key=path...>",
@@ -23047,8 +23107,10 @@ function registerCallCommand(parent, getContext2) {
23047
23107
  return arr;
23048
23108
  },
23049
23109
  []
23110
+ ).addOption(
23111
+ new import_commander4.Option("--env <environment>", "Environment: dev or prod").choices(["dev", "prod"])
23050
23112
  ).action(async (opts) => {
23051
- const { config, client } = getContext2();
23113
+ const { client } = getContext2();
23052
23114
  const method = opts.method || "GET";
23053
23115
  const filePayloads = await parseFileFlags(opts.file, client);
23054
23116
  let body = opts.body;
@@ -23080,31 +23142,6 @@ function registerCallCommand(parent, getContext2) {
23080
23142
  if (err.message?.startsWith("Unresolved file reference")) throw err;
23081
23143
  }
23082
23144
  }
23083
- const autoExec = process.argv.includes("--yes") || process.argv.includes("-y") || shouldAutoExecute(config.policies.callSystem, method, opts.url);
23084
- if (!autoExec) {
23085
- const methodColors = {
23086
- GET: c.green,
23087
- POST: c.yellow,
23088
- PUT: c.blue,
23089
- PATCH: c.magenta,
23090
- DELETE: c.red
23091
- };
23092
- const mc = methodColors[method.toUpperCase()] || c.white;
23093
- console.log("");
23094
- console.log(` ${mc}${c.bold}${method.toUpperCase()}${c.reset} ${opts.url}`);
23095
- if (opts.systemId) console.log(` ${c.dim}system:${c.reset} ${opts.systemId}`);
23096
- if (opts.headers) console.log(` ${c.dim}headers:${c.reset} ${opts.headers}`);
23097
- if (body) {
23098
- const preview = body.length > 200 ? body.slice(0, 200) + `${c.dim}...${c.reset}` : body;
23099
- console.log(` ${c.dim}body:${c.reset} ${preview}`);
23100
- }
23101
- console.log("");
23102
- const accepted = await confirm("Execute this request?");
23103
- if (!accepted) {
23104
- output({ success: false, cancelled: true, message: "Request cancelled" });
23105
- process.exit(0);
23106
- }
23107
- }
23108
23145
  let headers;
23109
23146
  if (opts.headers) {
23110
23147
  try {
@@ -23126,11 +23163,12 @@ function registerCallCommand(parent, getContext2) {
23126
23163
  }
23127
23164
  };
23128
23165
  try {
23129
- const result = await client.executeStep({ step, payload: {} });
23166
+ const mode = opts.env === "dev" || opts.env === "prod" ? opts.env : void 0;
23167
+ const result = await client.executeStep({ step, payload: {}, mode });
23130
23168
  const responseData = result.data?.data !== void 0 ? result.data.data : result.data;
23131
23169
  output({
23132
23170
  success: result.success,
23133
- protocol: (0, import_shared7.getConnectionProtocol)(opts.url),
23171
+ protocol: (0, import_shared8.getConnectionProtocol)(opts.url),
23134
23172
  data: responseData,
23135
23173
  ...result.error ? { error: result.error } : {}
23136
23174
  });
@@ -23144,7 +23182,7 @@ function registerCallCommand(parent, getContext2) {
23144
23182
 
23145
23183
  // src/commands/system/docs.ts
23146
23184
  function registerDocsCommand(parent, getContext2) {
23147
- parent.command("docs").description("Search system documentation").requiredOption("--system-id <id>", "System ID").requiredOption("--keywords <keywords>", "Search keywords").action(async (opts) => {
23185
+ parent.command("search-docs").description("Search system documentation by keywords").requiredOption("--system-id <id>", "System ID").requiredOption("-k, --keywords <keywords>", "Search keywords").action(async (opts) => {
23148
23186
  const { client } = getContext2();
23149
23187
  try {
23150
23188
  const result = await client.searchSystemDocumentation(opts.systemId, opts.keywords);
@@ -23191,7 +23229,7 @@ function registerDocsCommand(parent, getContext2) {
23191
23229
 
23192
23230
  // src/commands/system/oauth.ts
23193
23231
  var import_node_child_process2 = require("child_process");
23194
- var import_shared8 = __toESM(require_dist2());
23232
+ var import_shared9 = __toESM(require_dist2());
23195
23233
  function openBrowser(url) {
23196
23234
  const platform = process.platform;
23197
23235
  const cmd = platform === "darwin" ? "open" : platform === "win32" ? "cmd" : "xdg-open";
@@ -23227,7 +23265,7 @@ function registerOAuthCommand(parent, getContext2) {
23227
23265
  error(err.message);
23228
23266
  process.exit(1);
23229
23267
  }
23230
- const templateMatch = (0, import_shared8.findTemplateForSystem)(system);
23268
+ const templateMatch = (0, import_shared9.findTemplateForSystem)(system);
23231
23269
  const templateOAuth = templateMatch?.template?.oauth;
23232
23270
  const clientId = system.credentials?.client_id ?? templateOAuth?.client_id;
23233
23271
  const authUrl = opts.authUrl ?? system.credentials?.auth_url ?? templateOAuth?.authUrl;
@@ -23305,7 +23343,7 @@ function registerOAuthCommand(parent, getContext2) {
23305
23343
  error(`Failed to get OAuth encryption secret: ${err.message}`);
23306
23344
  process.exit(1);
23307
23345
  }
23308
- const encryptedApiKey = (0, import_shared8.encryptCliApiKey)(config.apiKey, opts.systemId, encryptionSecret);
23346
+ const encryptedApiKey = (0, import_shared9.encryptCliApiKey)(config.apiKey, opts.systemId, encryptionSecret);
23309
23347
  const redirectUri = `${config.webEndpoint.replace(/\/$/, "")}/api/auth/callback`;
23310
23348
  const state = {
23311
23349
  systemId: opts.systemId,
@@ -23481,45 +23519,44 @@ function registerUpdateCommand(program2) {
23481
23519
  }
23482
23520
 
23483
23521
  // src/cli.ts
23484
- var program = new import_commander.Command();
23485
- program.name("sg").description("superglue CLI \u2014 build, run, and manage integration tools").version(CLI_VERSION).option("--api-key <key>", "superglue API key").option("--endpoint <url>", "superglue API endpoint").option("--json", "force JSON output").option("-y, --yes", "auto-accept all confirmations").addHelpText(
23522
+ var program = new import_commander5.Command();
23523
+ program.name("sg").description("superglue CLI \u2014 build, run, and manage integration tools").version(CLI_VERSION).option("--api-key <key>", "superglue API key").option("--endpoint <url>", "superglue API endpoint").option("--json", "force JSON output").addHelpText(
23486
23524
  "after",
23487
23525
  `
23488
23526
  All Commands:
23489
- sg init Set up CLI configuration
23527
+ sg init Set up CLI configuration
23490
23528
 
23491
- sg tool build --config <file> Build a tool from a JSON config file
23492
- sg tool build --id <id> --instruction <t> Build a tool from flags (requires --steps <file>)
23493
- sg tool run --draft <id> [--payload <json>] Run a draft tool
23494
- sg tool run --tool <id> [--payload <json>] Run a saved tool
23495
- sg tool edit --tool <id> --patches <json> Edit a tool via JSON Patch operations
23496
- sg tool edit --draft <id> --patches <json> Edit a draft via JSON Patch operations
23497
- sg tool save <id> Save a draft tool to the server
23498
- sg tool list List all saved tools (IDs + instructions)
23499
- sg tool find [query] Search tools by keyword
23500
- sg tool find --id <id> Get full config of a specific tool
23529
+ sg tool build --config <file> Build a tool from a JSON config
23530
+ sg tool build --id <id> --instruction <text> Build a tool from flags (requires --steps)
23531
+ sg tool run --tool <id> [--payload <json>] Run a saved tool
23532
+ sg tool run --draft <id> [--payload <json>] Run a draft tool
23533
+ sg tool edit --tool <id> --patches <json> Edit a tool via JSON Patch
23534
+ sg tool edit --draft <id> --patches <json> Edit a draft via JSON Patch
23535
+ sg tool save --draft <id> Save a draft to the server
23536
+ sg tool list List all saved tools
23537
+ sg tool find [query] Search tools by keyword
23538
+ sg tool find --id <id> Get full config of a tool
23501
23539
 
23502
- sg system create --config <file> Create a system from a JSON config file
23503
- sg system create --id <id> --url <url> Create a system from flags
23504
- sg system edit <id> Edit a system's configuration
23505
- sg system list List all systems
23506
- sg system find [query] Search systems by keyword
23507
- sg system find --id <id> Get full config of a specific system
23508
- sg system call --url <url> [--method GET] Call an API/DB/file server with credential injection
23509
- sg system docs <id> View system documentation
23510
- sg system oauth <id> Authenticate a system via OAuth
23540
+ sg system create --config <file> Create a system from JSON config
23541
+ sg system create --id <id> --url <url> Create a system from flags
23542
+ sg system edit --id <id> Edit a system's configuration
23543
+ sg system list List all systems
23544
+ sg system find [query] Search systems by keyword
23545
+ sg system find --id <id> Get full config of a system
23546
+ sg system call --url <url> [--method GET] Call an API, database, or file server
23547
+ sg system search-docs --system-id <id> -k <kw> Search system documentation
23548
+ sg system oauth --system-id <id> --scopes <s> Authenticate a system via OAuth
23511
23549
 
23512
- sg run list [toolId] List execution runs, optionally filtered by tool
23513
- sg run get <runId> Get details of a specific run
23550
+ sg run list [toolId] List runs, optionally filtered by tool
23551
+ sg run get <runId> Get details of a specific run
23514
23552
 
23515
- sg update Update CLI to latest version
23516
- sg update --check Check for available updates
23553
+ sg update Update CLI to latest version
23554
+ sg update --check Check for available updates
23517
23555
 
23518
23556
  Global Flags:
23519
- --api-key <key> Override API key from config
23520
- --endpoint <url> Override API endpoint from config
23521
- --json Force JSON output (default in non-TTY)
23522
- -y, --yes Auto-accept all confirmations
23557
+ --api-key <key> Override API key from config
23558
+ --endpoint <url> Override API endpoint from config
23559
+ --json Force JSON output (default in non-TTY)
23523
23560
  `
23524
23561
  );
23525
23562
  var getContext = () => {
@@ -23535,7 +23572,7 @@ registerSystemCommands(program, getContext);
23535
23572
  registerRunCommands(program, getContext);
23536
23573
  var commandsRequiringServer = ["tool", "system", "run"];
23537
23574
  var globalFlagsWithValues = ["--api-key", "--endpoint"];
23538
- var globalFlagsNoValue = ["--json", "-y", "--yes", "-h", "--help", "-V", "--version"];
23575
+ var globalFlagsNoValue = ["--json", "-h", "--help", "-V", "--version"];
23539
23576
  function findSubcommand(argv) {
23540
23577
  let i = 2;
23541
23578
  while (i < argv.length) {