@superglue/cli 1.0.0 → 1.1.1

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 RequestSource3;
1854
+ (function(RequestSource4) {
1855
+ RequestSource4["API"] = "api";
1856
+ RequestSource4["FRONTEND"] = "frontend";
1857
+ RequestSource4["SCHEDULER"] = "scheduler";
1858
+ RequestSource4["MCP"] = "mcp";
1859
+ RequestSource4["TOOL_CHAIN"] = "tool-chain";
1860
+ RequestSource4["WEBHOOK"] = "webhook";
1861
+ RequestSource4["CLI"] = "cli";
1862
+ })(RequestSource3 || (exports2.RequestSource = RequestSource3 = {}));
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";
@@ -8813,8 +8818,8 @@ var require_luxon = __commonJS({
8813
8818
  let current = null, currentFull = "", bracketed = false;
8814
8819
  const splits = [];
8815
8820
  for (let i = 0; i < fmt.length; i++) {
8816
- const c2 = fmt.charAt(i);
8817
- if (c2 === "'") {
8821
+ const c3 = fmt.charAt(i);
8822
+ if (c3 === "'") {
8818
8823
  if (currentFull.length > 0 || bracketed) {
8819
8824
  splits.push({
8820
8825
  literal: bracketed || /^\s+$/.test(currentFull),
@@ -8825,9 +8830,9 @@ var require_luxon = __commonJS({
8825
8830
  currentFull = "";
8826
8831
  bracketed = !bracketed;
8827
8832
  } else if (bracketed) {
8828
- currentFull += c2;
8829
- } else if (c2 === current) {
8830
- currentFull += c2;
8833
+ currentFull += c3;
8834
+ } else if (c3 === current) {
8835
+ currentFull += c3;
8831
8836
  } else {
8832
8837
  if (currentFull.length > 0) {
8833
8838
  splits.push({
@@ -8835,8 +8840,8 @@ var require_luxon = __commonJS({
8835
8840
  val: currentFull
8836
8841
  });
8837
8842
  }
8838
- currentFull = c2;
8839
- current = c2;
8843
+ currentFull = c3;
8844
+ current = c3;
8840
8845
  }
8841
8846
  }
8842
8847
  if (currentFull.length > 0) {
@@ -11518,7 +11523,7 @@ var require_luxon = __commonJS({
11518
11523
  return fixOffset(objToLocalTS(obj), offset2, zone);
11519
11524
  }
11520
11525
  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 = {
11526
+ 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
11527
  ...inst.c,
11523
11528
  year,
11524
11529
  month,
@@ -11533,7 +11538,7 @@ var require_luxon = __commonJS({
11533
11538
  minutes: dur.minutes,
11534
11539
  seconds: dur.seconds,
11535
11540
  milliseconds: dur.milliseconds
11536
- }).as("milliseconds"), localTS = objToLocalTS(c2);
11541
+ }).as("milliseconds"), localTS = objToLocalTS(c3);
11537
11542
  let [ts, o] = fixOffset(localTS, oPre, inst.zone);
11538
11543
  if (millisToAdd !== 0) {
11539
11544
  ts += millisToAdd;
@@ -11568,72 +11573,72 @@ var require_luxon = __commonJS({
11568
11573
  }
11569
11574
  function toISODate(o, extended, precision) {
11570
11575
  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;
11576
+ let c3 = "";
11577
+ if (longFormat && o.c.year >= 0) c3 += "+";
11578
+ c3 += padStart(o.c.year, longFormat ? 6 : 4);
11579
+ if (precision === "year") return c3;
11575
11580
  if (extended) {
11576
- c2 += "-";
11577
- c2 += padStart(o.c.month);
11578
- if (precision === "month") return c2;
11579
- c2 += "-";
11581
+ c3 += "-";
11582
+ c3 += padStart(o.c.month);
11583
+ if (precision === "month") return c3;
11584
+ c3 += "-";
11580
11585
  } else {
11581
- c2 += padStart(o.c.month);
11582
- if (precision === "month") return c2;
11586
+ c3 += padStart(o.c.month);
11587
+ if (precision === "month") return c3;
11583
11588
  }
11584
- c2 += padStart(o.c.day);
11585
- return c2;
11589
+ c3 += padStart(o.c.day);
11590
+ return c3;
11586
11591
  }
11587
11592
  function toISOTime(o, extended, suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision) {
11588
- let showSeconds = !suppressSeconds || o.c.millisecond !== 0 || o.c.second !== 0, c2 = "";
11593
+ let showSeconds = !suppressSeconds || o.c.millisecond !== 0 || o.c.second !== 0, c3 = "";
11589
11594
  switch (precision) {
11590
11595
  case "day":
11591
11596
  case "month":
11592
11597
  case "year":
11593
11598
  break;
11594
11599
  default:
11595
- c2 += padStart(o.c.hour);
11600
+ c3 += padStart(o.c.hour);
11596
11601
  if (precision === "hour") break;
11597
11602
  if (extended) {
11598
- c2 += ":";
11599
- c2 += padStart(o.c.minute);
11603
+ c3 += ":";
11604
+ c3 += padStart(o.c.minute);
11600
11605
  if (precision === "minute") break;
11601
11606
  if (showSeconds) {
11602
- c2 += ":";
11603
- c2 += padStart(o.c.second);
11607
+ c3 += ":";
11608
+ c3 += padStart(o.c.second);
11604
11609
  }
11605
11610
  } else {
11606
- c2 += padStart(o.c.minute);
11611
+ c3 += padStart(o.c.minute);
11607
11612
  if (precision === "minute") break;
11608
11613
  if (showSeconds) {
11609
- c2 += padStart(o.c.second);
11614
+ c3 += padStart(o.c.second);
11610
11615
  }
11611
11616
  }
11612
11617
  if (precision === "second") break;
11613
11618
  if (showSeconds && (!suppressMilliseconds || o.c.millisecond !== 0)) {
11614
- c2 += ".";
11615
- c2 += padStart(o.c.millisecond, 3);
11619
+ c3 += ".";
11620
+ c3 += padStart(o.c.millisecond, 3);
11616
11621
  }
11617
11622
  }
11618
11623
  if (includeOffset) {
11619
11624
  if (o.isOffsetFixed && o.offset === 0 && !extendedZone) {
11620
- c2 += "Z";
11625
+ c3 += "Z";
11621
11626
  } 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));
11627
+ c3 += "-";
11628
+ c3 += padStart(Math.trunc(-o.o / 60));
11629
+ c3 += ":";
11630
+ c3 += padStart(Math.trunc(-o.o % 60));
11626
11631
  } else {
11627
- c2 += "+";
11628
- c2 += padStart(Math.trunc(o.o / 60));
11629
- c2 += ":";
11630
- 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));
11631
11636
  }
11632
11637
  }
11633
11638
  if (extendedZone) {
11634
- c2 += "[" + o.zone.ianaName + "]";
11639
+ c3 += "[" + o.zone.ianaName + "]";
11635
11640
  }
11636
- return c2;
11641
+ return c3;
11637
11642
  }
11638
11643
  var defaultUnitValues = {
11639
11644
  month: 1,
@@ -11751,10 +11756,10 @@ var require_luxon = __commonJS({
11751
11756
  });
11752
11757
  }
11753
11758
  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);
11759
+ const round = isUndefined(opts.round) ? true : opts.round, rounding = isUndefined(opts.rounding) ? "trunc" : opts.rounding, format = (c3, unit) => {
11760
+ c3 = roundTo(c3, round || opts.calendary ? 0 : 2, opts.calendary ? "round" : rounding);
11756
11761
  const formatter = end.loc.clone(opts).relFormatter(opts);
11757
- return formatter.format(c2, unit);
11762
+ return formatter.format(c3, unit);
11758
11763
  }, differ = (unit) => {
11759
11764
  if (opts.calendary) {
11760
11765
  if (!end.hasSame(start, unit)) {
@@ -11795,16 +11800,16 @@ var require_luxon = __commonJS({
11795
11800
  const zone = config.zone || Settings.defaultZone;
11796
11801
  let invalid = config.invalid || (Number.isNaN(config.ts) ? new Invalid("invalid input") : null) || (!zone.isValid ? unsupportedZone(zone) : null);
11797
11802
  this.ts = isUndefined(config.ts) ? Settings.now() : config.ts;
11798
- let c2 = null, o = null;
11803
+ let c3 = null, o = null;
11799
11804
  if (!invalid) {
11800
11805
  const unchanged = config.old && config.old.ts === this.ts && config.old.zone.equals(zone);
11801
11806
  if (unchanged) {
11802
- [c2, o] = [config.old.c, config.old.o];
11807
+ [c3, o] = [config.old.c, config.old.o];
11803
11808
  } else {
11804
11809
  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;
11810
+ c3 = tsToObj(this.ts, ot);
11811
+ invalid = Number.isNaN(c3.year) ? new Invalid("invalid input") : null;
11812
+ c3 = invalid ? null : c3;
11808
11813
  o = invalid ? null : ot;
11809
11814
  }
11810
11815
  }
@@ -11813,7 +11818,7 @@ var require_luxon = __commonJS({
11813
11818
  this.invalid = invalid;
11814
11819
  this.weekData = null;
11815
11820
  this.localWeekData = null;
11816
- this.c = c2;
11821
+ this.c = c3;
11817
11822
  this.o = o;
11818
11823
  this.isLuxonDateTime = true;
11819
11824
  }
@@ -12572,8 +12577,8 @@ var require_luxon = __commonJS({
12572
12577
  const ts1 = localTS - o1 * minuteMs;
12573
12578
  const ts2 = localTS - o2 * minuteMs;
12574
12579
  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) {
12580
+ const c22 = tsToObj(ts2, o2);
12581
+ if (c1.hour === c22.hour && c1.minute === c22.minute && c1.second === c22.second && c1.millisecond === c22.millisecond) {
12577
12582
  return [clone2(this, {
12578
12583
  ts: ts1
12579
12584
  }), clone2(this, {
@@ -12971,10 +12976,10 @@ var require_luxon = __commonJS({
12971
12976
  }
12972
12977
  precision = normalizeUnit(precision);
12973
12978
  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;
12979
+ let c3 = toISODate(this, ext, precision);
12980
+ if (orderedUnits.indexOf(precision) >= 3) c3 += "T";
12981
+ c3 += toISOTime(this, ext, suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision);
12982
+ return c3;
12978
12983
  }
12979
12984
  /**
12980
12985
  * Returns an ISO 8601-compliant string representation of this DateTime's date component
@@ -13033,8 +13038,8 @@ var require_luxon = __commonJS({
13033
13038
  return null;
13034
13039
  }
13035
13040
  precision = normalizeUnit(precision);
13036
- let c2 = includePrefix && orderedUnits.indexOf(precision) >= 3 ? "T" : "";
13037
- return c2 + toISOTime(this, format === "extended", suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision);
13041
+ let c3 = includePrefix && orderedUnits.indexOf(precision) >= 3 ? "T" : "";
13042
+ return c3 + toISOTime(this, format === "extended", suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision);
13038
13043
  }
13039
13044
  /**
13040
13045
  * Returns an RFC 2822-compatible string representation of this DateTime
@@ -17619,7 +17624,7 @@ attempted value: ${formattedValue}
17619
17624
  type: next.type,
17620
17625
  oneOf: next._whitelist.describe(),
17621
17626
  notOneOf: next._blacklist.describe(),
17622
- tests: next.tests.filter((n, idx, list) => list.findIndex((c2) => c2.OPTIONS.name === n.OPTIONS.name) === idx).map((fn) => {
17627
+ tests: next.tests.filter((n, idx, list) => list.findIndex((c3) => c3.OPTIONS.name === n.OPTIONS.name) === idx).map((fn) => {
17623
17628
  const params = fn.OPTIONS.params && options ? resolveParams(Object.assign({}, fn.OPTIONS.params), options) : fn.OPTIONS.params;
17624
17629
  return {
17625
17630
  name: fn.OPTIONS.name,
@@ -19867,6 +19872,7 @@ var require_utils = __commonJS({
19867
19872
  exports2.ALLOWED_PATCH_SYSTEM_FIELDS = exports2.getSystemAuthStatus = exports2.detectSystemAuthType = exports2.maskSystemCredentials = exports2.isSensitiveCredentialKey = exports2.ALLOWED_FILE_EXTENSIONS = exports2.getConnectionProtocol = void 0;
19868
19873
  exports2.validateExternalUrl = validateExternalUrl;
19869
19874
  exports2.flattenAndNamespaceCredentials = flattenAndNamespaceCredentials;
19875
+ exports2.flattenAndNamespaceSystemUrls = flattenAndNamespaceSystemUrls;
19870
19876
  exports2.generateUniqueId = generateUniqueId;
19871
19877
  exports2.waitForSystemProcessing = waitForSystemProcessing;
19872
19878
  exports2.inferJsonSchema = inferJsonSchema;
@@ -20067,6 +20073,14 @@ var require_utils = __commonJS({
20067
20073
  return acc;
20068
20074
  }, {});
20069
20075
  }
20076
+ function flattenAndNamespaceSystemUrls(systems2) {
20077
+ return systems2.reduce((acc, sys) => {
20078
+ if (sys.url) {
20079
+ acc[`${sys.id}_url`] = sys.url;
20080
+ }
20081
+ return acc;
20082
+ }, {});
20083
+ }
20070
20084
  async function generateUniqueId({ baseId, exists }) {
20071
20085
  if (!await exists(baseId)) {
20072
20086
  return baseId;
@@ -20448,6 +20462,7 @@ var require_utils = __commonJS({
20448
20462
  "multiTenancyMode",
20449
20463
  "documentationFiles",
20450
20464
  "tunnel"
20465
+ // Note: "environment" is NOT patchable because it's part of the composite primary key
20451
20466
  ];
20452
20467
  var SAMPLEABLE_KEYS = /* @__PURE__ */ new Set([
20453
20468
  "data",
@@ -21096,9 +21111,9 @@ var require_superglue_client = __commonJS({
21096
21111
  var types_js_1 = require_types();
21097
21112
  var sse_log_subscription_js_1 = require_sse_log_subscription();
21098
21113
  var SuperglueClient3 = class {
21099
- constructor({ endpoint, apiKey, apiEndpoint, onInfrastructureError }) {
21114
+ constructor({ apiKey, apiEndpoint, onInfrastructureError }) {
21100
21115
  this.apiKey = apiKey;
21101
- this.apiEndpoint = apiEndpoint ?? endpoint ?? "https://api.superglue.cloud";
21116
+ this.apiEndpoint = apiEndpoint ?? "https://api.superglue.cloud";
21102
21117
  this.sseManager = new sse_log_subscription_js_1.SSELogSubscriptionManager(this.apiEndpoint, this.apiKey);
21103
21118
  this.onInfrastructureError = onInfrastructureError;
21104
21119
  }
@@ -21218,14 +21233,15 @@ var require_superglue_client = __commonJS({
21218
21233
  * Execute a single step without creating a run in the database.
21219
21234
  * Used for individual step testing in the playground.
21220
21235
  */
21221
- async executeStep({ step, payload, previousResults, credentials, options, runId }) {
21236
+ async executeStep({ step, payload, previousResults, credentials, options, runId, mode }) {
21222
21237
  return this.restRequest("POST", "/v1/tools/step/run", {
21223
21238
  step,
21224
21239
  payload,
21225
21240
  previousResults,
21226
21241
  credentials,
21227
21242
  options,
21228
- runId
21243
+ runId,
21244
+ mode
21229
21245
  });
21230
21246
  }
21231
21247
  /**
@@ -21400,11 +21416,14 @@ var require_superglue_client = __commonJS({
21400
21416
  newId
21401
21417
  });
21402
21418
  }
21403
- async listSystems(limit = 10, page = 1) {
21419
+ async listSystems(limit = 10, page = 1, options) {
21404
21420
  const params = new URLSearchParams({
21405
21421
  limit: String(limit),
21406
21422
  page: String(page)
21407
21423
  });
21424
+ if (options?.mode) {
21425
+ params.set("mode", options.mode);
21426
+ }
21408
21427
  const response = await this.restRequest("GET", `/v1/systems?${params.toString()}`);
21409
21428
  return { items: response.data, total: response.total };
21410
21429
  }
@@ -21413,20 +21432,23 @@ var require_superglue_client = __commonJS({
21413
21432
  const response = await this.restRequest("GET", `/v1/tools/search${params}`);
21414
21433
  return response.data;
21415
21434
  }
21416
- async getSystem(id) {
21417
- const response = await this.restRequest("GET", `/v1/systems/${encodeURIComponent(id)}`);
21435
+ async getSystem(id, options) {
21436
+ const queryParams = options?.environment ? `?env=${options.environment}` : "";
21437
+ const response = await this.restRequest("GET", `/v1/systems/${encodeURIComponent(id)}${queryParams}`);
21418
21438
  return response.data;
21419
21439
  }
21420
21440
  async createSystem(input) {
21421
21441
  const response = await this.restRequest("POST", "/v1/systems", input);
21422
21442
  return response.data;
21423
21443
  }
21424
- async updateSystem(id, input) {
21425
- const response = await this.restRequest("PATCH", `/v1/systems/${encodeURIComponent(id)}`, input);
21444
+ async updateSystem(id, input, options) {
21445
+ const queryParams = options?.environment ? `?env=${options.environment}` : "";
21446
+ const response = await this.restRequest("PATCH", `/v1/systems/${encodeURIComponent(id)}${queryParams}`, input);
21426
21447
  return response.data;
21427
21448
  }
21428
- async deleteSystem(id) {
21429
- await this.restRequest("DELETE", `/v1/systems/${encodeURIComponent(id)}`);
21449
+ async deleteSystem(id, options) {
21450
+ const queryParams = options?.environment ? `?env=${options.environment}` : "";
21451
+ await this.restRequest("DELETE", `/v1/systems/${encodeURIComponent(id)}${queryParams}`);
21430
21452
  return true;
21431
21453
  }
21432
21454
  async cacheOAuthSecret(args) {
@@ -21584,18 +21606,14 @@ var require_dist2 = __commonJS({
21584
21606
  });
21585
21607
 
21586
21608
  // src/cli.ts
21587
- var import_commander = require("commander");
21609
+ var import_commander5 = require("commander");
21588
21610
 
21589
21611
  // src/config.ts
21590
21612
  var fs = __toESM(require("fs"));
21591
21613
  var os = __toESM(require("os"));
21592
21614
  var path = __toESM(require("path"));
21593
21615
  var DEFAULT_CONFIG = {
21594
- output: { mode: "stdout", directory: ".superglue/output" },
21595
- policies: {
21596
- callSystem: "ask_every_time",
21597
- editTool: "confirm"
21598
- }
21616
+ output: { mode: "stdout", directory: ".superglue/output" }
21599
21617
  };
21600
21618
  function getConfigDir(preferLocal) {
21601
21619
  const localDir = path.join(process.cwd(), ".superglue");
@@ -21638,14 +21656,15 @@ function resolveConfig(flags) {
21638
21656
  apiKey,
21639
21657
  endpoint,
21640
21658
  webEndpoint,
21641
- output: { ...DEFAULT_CONFIG.output, ...file.output },
21642
- policies: { ...DEFAULT_CONFIG.policies, ...file.policies }
21659
+ output: { ...DEFAULT_CONFIG.output, ...file.output }
21643
21660
  };
21644
21661
  }
21645
21662
  function writeConfig(config, preferLocal) {
21646
21663
  const dir = getConfigDir(preferLocal);
21647
21664
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
21648
- fs.writeFileSync(path.join(dir, "config.json"), JSON.stringify(config, null, 2) + "\n");
21665
+ fs.writeFileSync(path.join(dir, "config.json"), JSON.stringify(config, null, 2) + "\n", {
21666
+ mode: 384
21667
+ });
21649
21668
  }
21650
21669
  function ensureConfigDirs(config, preferLocal) {
21651
21670
  const draftsDir = path.join(getConfigDir(preferLocal), "drafts");
@@ -21677,6 +21696,126 @@ var import_shared2 = __toESM(require_dist2());
21677
21696
 
21678
21697
  // src/output.ts
21679
21698
  var readline = __toESM(require("readline"));
21699
+
21700
+ // src/version.ts
21701
+ var import_node_child_process = require("child_process");
21702
+ var import_node_util = require("util");
21703
+
21704
+ // package.json
21705
+ var package_default = {
21706
+ name: "@superglue/cli",
21707
+ version: "1.1.0",
21708
+ bin: {
21709
+ sg: "./dist/cli.js"
21710
+ },
21711
+ files: [
21712
+ ".claude-plugin/",
21713
+ "dist/",
21714
+ "skills/",
21715
+ "LICENSE"
21716
+ ],
21717
+ dependencies: {
21718
+ commander: "^13.0.0",
21719
+ "fast-json-patch": "^3.1.1"
21720
+ },
21721
+ devDependencies: {
21722
+ "@superglue/shared": "file:../shared",
21723
+ "@types/node": "^20.0.0",
21724
+ tsup: "^8.0.0",
21725
+ typescript: "^5.0.0"
21726
+ },
21727
+ scripts: {
21728
+ build: "tsup && (cp -r skills dist/ 2>/dev/null || true)",
21729
+ dev: "tsup --watch",
21730
+ "type-check": "tsc --noEmit",
21731
+ prepublishOnly: "npm run build"
21732
+ },
21733
+ publishConfig: {
21734
+ access: "public"
21735
+ }
21736
+ };
21737
+
21738
+ // src/version.ts
21739
+ var execAsync = (0, import_node_util.promisify)(import_node_child_process.exec);
21740
+ var CLI_VERSION = package_default.version;
21741
+ function parseVersionPart(part) {
21742
+ const match = part.match(/^(\d+)(?:-(.+))?$/);
21743
+ if (match) {
21744
+ return { numeric: parseInt(match[1], 10), prerelease: match[2] || null };
21745
+ }
21746
+ return { numeric: 0, prerelease: part };
21747
+ }
21748
+ function compareVersions(a, b) {
21749
+ const partsA = a.split(".");
21750
+ const partsB = b.split(".");
21751
+ const maxLen = Math.max(partsA.length, partsB.length);
21752
+ for (let i = 0; i < maxLen; i++) {
21753
+ const parsedA = parseVersionPart(partsA[i] || "0");
21754
+ const parsedB = parseVersionPart(partsB[i] || "0");
21755
+ if (parsedA.numeric < parsedB.numeric) return -1;
21756
+ if (parsedA.numeric > parsedB.numeric) return 1;
21757
+ if (parsedA.prerelease === null && parsedB.prerelease !== null) return 1;
21758
+ if (parsedA.prerelease !== null && parsedB.prerelease === null) return -1;
21759
+ if (parsedA.prerelease !== null && parsedB.prerelease !== null) {
21760
+ if (parsedA.prerelease < parsedB.prerelease) return -1;
21761
+ if (parsedA.prerelease > parsedB.prerelease) return 1;
21762
+ }
21763
+ }
21764
+ return 0;
21765
+ }
21766
+ async function checkVersionCompatibility(endpoint) {
21767
+ try {
21768
+ const healthUrl = `${endpoint.replace(/\/$/, "")}/v1/health`;
21769
+ const response = await fetch(healthUrl, { signal: AbortSignal.timeout(3e3) });
21770
+ if (!response.ok) return;
21771
+ const health = await response.json();
21772
+ if (!health.minCliVersion) return;
21773
+ if (compareVersions(CLI_VERSION, health.minCliVersion) < 0) {
21774
+ console.error("");
21775
+ console.error(`${c.yellow}${c.bold}\u26A0 CLI version ${CLI_VERSION} is outdated.${c.reset}`);
21776
+ console.error(
21777
+ `${c.yellow} Server requires at least v${health.minCliVersion}. Run: ${c.bold}sg update${c.reset}`
21778
+ );
21779
+ console.error("");
21780
+ }
21781
+ } catch {
21782
+ }
21783
+ }
21784
+ async function getLatestNpmVersion() {
21785
+ try {
21786
+ const response = await fetch("https://registry.npmjs.org/@superglue/cli/latest", {
21787
+ signal: AbortSignal.timeout(5e3)
21788
+ });
21789
+ if (!response.ok) return null;
21790
+ const data = await response.json();
21791
+ return data.version || null;
21792
+ } catch {
21793
+ return null;
21794
+ }
21795
+ }
21796
+ async function updateCli() {
21797
+ const latestVersion = await getLatestNpmVersion();
21798
+ if (!latestVersion) {
21799
+ return { success: false, message: "Could not fetch latest version from npm" };
21800
+ }
21801
+ if (compareVersions(CLI_VERSION, latestVersion) >= 0) {
21802
+ return { success: true, message: `Already on latest version (${CLI_VERSION})` };
21803
+ }
21804
+ try {
21805
+ await execAsync("npm install -g @superglue/cli@latest");
21806
+ return {
21807
+ success: true,
21808
+ message: `Updated from ${CLI_VERSION} to ${latestVersion}`
21809
+ };
21810
+ } catch (err) {
21811
+ return {
21812
+ success: false,
21813
+ message: `Update failed: ${err.message}. Try manually: npm install -g @superglue/cli@latest`
21814
+ };
21815
+ }
21816
+ }
21817
+
21818
+ // src/output.ts
21680
21819
  var isJsonMode = () => process.argv.includes("--json") || !process.stdout.isTTY;
21681
21820
  var c = {
21682
21821
  reset: "\x1B[0m",
@@ -21699,6 +21838,10 @@ var c = {
21699
21838
  bgMagenta: "\x1B[45m",
21700
21839
  bgCyan: "\x1B[46m"
21701
21840
  };
21841
+ function link(url, label) {
21842
+ const text = label || url;
21843
+ return `\x1B]8;;${url}\x07${c.underline}${c.cyan}${text}${c.reset}\x1B]8;;\x07`;
21844
+ }
21702
21845
  function banner() {
21703
21846
  if (isJsonMode()) return;
21704
21847
  const rst = c.reset;
@@ -21729,26 +21872,34 @@ function banner() {
21729
21872
  const after = line.slice(last + 1);
21730
21873
  console.log(` ${before}${inv}${inside}${rst}${after}`);
21731
21874
  });
21732
- console.log(` ${d} CLI v0.1.0${rst}`);
21875
+ console.log(` ${d} CLI v${CLI_VERSION}${rst}`);
21733
21876
  console.log("");
21734
21877
  }
21735
21878
  function spinner(message) {
21736
21879
  if (isJsonMode()) return { stop: () => {
21737
21880
  }, update: () => {
21881
+ }, log: () => {
21738
21882
  } };
21739
21883
  const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
21740
21884
  let i = 0;
21741
21885
  let currentMsg = message;
21742
- const interval = setInterval(() => {
21886
+ const clearLine = () => process.stdout.write(`\r\x1B[2K`);
21887
+ const drawSpinner = () => {
21743
21888
  process.stdout.write(`\r ${c.cyan}${frames[i++ % frames.length]}${c.reset} ${currentMsg}`);
21744
- }, 80);
21889
+ };
21890
+ const interval = setInterval(drawSpinner, 80);
21745
21891
  return {
21746
21892
  update: (msg) => {
21747
21893
  currentMsg = msg;
21748
21894
  },
21895
+ log: (line) => {
21896
+ clearLine();
21897
+ console.log(` ${c.dim}\u2502${c.reset} ${line}`);
21898
+ drawSpinner();
21899
+ },
21749
21900
  stop: (finalMsg) => {
21750
21901
  clearInterval(interval);
21751
- process.stdout.write(`\r${"".padEnd(currentMsg.length + 10)}\r`);
21902
+ clearLine();
21752
21903
  if (finalMsg) console.log(` ${finalMsg}`);
21753
21904
  }
21754
21905
  };
@@ -21782,6 +21933,11 @@ function error(message, details) {
21782
21933
  if (details) prettyPrint(details, 4);
21783
21934
  }
21784
21935
  }
21936
+ function warn(message) {
21937
+ if (!isJsonMode()) {
21938
+ console.log(` ${c.yellow}\u26A0${c.reset} ${message}`);
21939
+ }
21940
+ }
21785
21941
  function info(message) {
21786
21942
  if (!isJsonMode()) {
21787
21943
  console.log(` ${c.dim}${message}${c.reset}`);
@@ -21944,16 +22100,6 @@ function renderDiffs(diffs) {
21944
22100
  return ` ${color}${icon} ${c.bold}[${d.op}]${c.reset} ${c.dim}${d.path}${c.reset}${valueStr}`;
21945
22101
  }).join("\n");
21946
22102
  }
21947
- async function confirm(message) {
21948
- if (process.argv.includes("--yes") || process.argv.includes("-y")) return true;
21949
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
21950
- return new Promise((resolve4) => {
21951
- rl.question(` ${message} ${c.dim}[y/N]${c.reset} `, (answer) => {
21952
- rl.close();
21953
- resolve4(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
21954
- });
21955
- });
21956
- }
21957
22103
  async function prompt(message, defaultValue) {
21958
22104
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
21959
22105
  const suffix = defaultValue ? ` ${c.dim}[${defaultValue}]${c.reset}` : "";
@@ -21966,47 +22112,97 @@ async function prompt(message, defaultValue) {
21966
22112
  }
21967
22113
  async function promptHidden(message) {
21968
22114
  return new Promise((resolve4) => {
21969
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
21970
- process.stdout.write(` ${message}: `);
21971
- if (process.stdin.isTTY) {
21972
- process.stdin.setRawMode(true);
22115
+ process.stdout.write(`${message}: `);
22116
+ if (!process.stdin.isTTY) {
22117
+ const rl = readline.createInterface({ input: process.stdin });
22118
+ rl.once("line", (line) => {
22119
+ rl.close();
22120
+ resolve4(line.trim());
22121
+ });
22122
+ return;
21973
22123
  }
22124
+ process.stdin.setRawMode(true);
22125
+ process.stdin.resume();
21974
22126
  let input = "";
21975
22127
  const onData = (ch) => {
21976
22128
  const s = ch.toString();
21977
- if (s === "\n" || s === "\r") {
21978
- if (process.stdin.isTTY) process.stdin.setRawMode(false);
21979
- process.stdin.removeListener("data", onData);
21980
- process.stdout.write("\n");
21981
- rl.close();
21982
- resolve4(input);
21983
- } else if (s === "") {
21984
- process.exit(0);
21985
- } else if (s === "\x7F" || s === "\b") {
21986
- if (input.length > 0) {
21987
- input = input.slice(0, -1);
21988
- process.stdout.write("\b \b");
22129
+ for (const char of s) {
22130
+ if (char === "\n" || char === "\r") {
22131
+ process.stdin.setRawMode(false);
22132
+ process.stdin.removeListener("data", onData);
22133
+ process.stdin.pause();
22134
+ process.stdout.write("\n");
22135
+ resolve4(input);
22136
+ return;
22137
+ } else if (char === "") {
22138
+ process.stdin.setRawMode(false);
22139
+ process.exit(130);
22140
+ } else if (char === "\x7F" || char === "\b") {
22141
+ if (input.length > 0) {
22142
+ input = input.slice(0, -1);
22143
+ process.stdout.write("\b \b");
22144
+ }
22145
+ } else {
22146
+ input += char;
22147
+ process.stdout.write(`${c.dim}\u2022${c.reset}`);
21989
22148
  }
21990
- } else {
21991
- input += s;
21992
- process.stdout.write(`${c.dim}\u2022${c.reset}`);
21993
22149
  }
21994
22150
  };
21995
22151
  process.stdin.on("data", onData);
21996
- process.stdin.resume();
21997
22152
  });
21998
22153
  }
21999
22154
  async function choose(message, options, defaultIndex = 0) {
22000
22155
  if (!process.stdout.isTTY) return defaultIndex;
22001
- console.log("");
22002
- for (let i = 0; i < options.length; i++) {
22003
- const marker = i === defaultIndex ? `${c.cyan}\u276F${c.reset}` : " ";
22004
- const label = i === defaultIndex ? `${c.bold}${options[i]}${c.reset}` : `${c.dim}${options[i]}${c.reset}`;
22005
- console.log(` ${marker} ${c.dim}(${i + 1})${c.reset} ${label}`);
22006
- }
22007
- const answer = await prompt(` ${message}`, String(defaultIndex + 1));
22008
- const idx = parseInt(answer, 10) - 1;
22009
- return idx >= 0 && idx < options.length ? idx : defaultIndex;
22156
+ let selected = defaultIndex;
22157
+ const render = () => {
22158
+ for (let i = 0; i < options.length; i++) {
22159
+ const marker = i === selected ? `${c.cyan}\u276F${c.reset}` : " ";
22160
+ const label = i === selected ? `${c.bold}${options[i]}${c.reset}` : `${c.dim}${options[i]}${c.reset}`;
22161
+ console.log(` ${marker} ${label}`);
22162
+ }
22163
+ };
22164
+ const moveUp = () => {
22165
+ process.stdout.write(`\x1B[${options.length}A\r`);
22166
+ for (let i = 0; i < options.length; i++) {
22167
+ process.stdout.write(`\x1B[2K`);
22168
+ if (i < options.length - 1) process.stdout.write(`
22169
+ `);
22170
+ }
22171
+ process.stdout.write(`\x1B[${options.length - 1}A\r`);
22172
+ };
22173
+ console.log(
22174
+ `
22175
+ ${c.bold}${message}${c.reset} ${c.dim}(\u2191/\u2193 to select, enter to confirm)${c.reset}`
22176
+ );
22177
+ render();
22178
+ return new Promise((resolve4) => {
22179
+ process.stdin.setRawMode(true);
22180
+ process.stdin.resume();
22181
+ const onData = (ch) => {
22182
+ const s = ch.toString();
22183
+ if (s === "\r" || s === "\n") {
22184
+ process.stdin.setRawMode(false);
22185
+ process.stdin.removeListener("data", onData);
22186
+ process.stdin.pause();
22187
+ resolve4(selected);
22188
+ return;
22189
+ }
22190
+ if (s === "") {
22191
+ process.stdin.setRawMode(false);
22192
+ process.exit(130);
22193
+ }
22194
+ if (s === "\x1B[A" || s === "k") {
22195
+ selected = (selected - 1 + options.length) % options.length;
22196
+ } else if (s === "\x1B[B" || s === "j") {
22197
+ selected = (selected + 1) % options.length;
22198
+ } else {
22199
+ return;
22200
+ }
22201
+ moveUp();
22202
+ render();
22203
+ };
22204
+ process.stdin.on("data", onData);
22205
+ });
22010
22206
  }
22011
22207
 
22012
22208
  // src/commands/init.ts
@@ -22017,6 +22213,10 @@ function registerInitCommand(program2) {
22017
22213
  console.log(` ${c.dim}Let's get you connected in a few steps.${c.reset}
22018
22214
  `);
22019
22215
  heading("Authentication");
22216
+ console.log(
22217
+ ` ${c.dim}Get your API key at${c.reset} ${link("https://app.superglue.cloud/admin?view=api-keys")}`
22218
+ );
22219
+ console.log("");
22020
22220
  const apiKey = await promptHidden(" API Key");
22021
22221
  if (!apiKey) {
22022
22222
  error("API key is required");
@@ -22049,25 +22249,6 @@ function registerInitCommand(program2) {
22049
22249
  if (outputMode === "stdout+file") {
22050
22250
  outputDir = await prompt(" Output directory", ".superglue/output");
22051
22251
  }
22052
- heading("Execution Policies");
22053
- console.log(` ${c.dim}These control when the CLI asks for confirmation.${c.reset}
22054
- `);
22055
- const callPolicyIdx = await choose(
22056
- "API call confirmation",
22057
- ["Ask every time", "Auto-run GET requests only", "Auto-run everything"],
22058
- 0
22059
- );
22060
- const callPolicies = [
22061
- "ask_every_time",
22062
- "run_gets_only",
22063
- "run_everything"
22064
- ];
22065
- const editPolicyIdx = await choose(
22066
- "Tool edit confirmation",
22067
- ["Show diff and ask to confirm", "Auto-accept all changes"],
22068
- 0
22069
- );
22070
- const editPolicies = ["confirm", "auto_accept"];
22071
22252
  heading("Config Location");
22072
22253
  const homeDir = os2.homedir();
22073
22254
  const localPath = path2.join(process.cwd(), ".superglue");
@@ -22085,11 +22266,7 @@ function registerInitCommand(program2) {
22085
22266
  apiKey,
22086
22267
  endpoint,
22087
22268
  webEndpoint,
22088
- output: { mode: outputMode, directory: outputDir },
22089
- policies: {
22090
- callSystem: callPolicies[callPolicyIdx],
22091
- editTool: editPolicies[editPolicyIdx]
22092
- }
22269
+ output: { mode: outputMode, directory: outputDir }
22093
22270
  };
22094
22271
  writeConfig(config, preferLocal);
22095
22272
  ensureConfigDirs(config, preferLocal);
@@ -22151,9 +22328,11 @@ var path3 = __toESM(require("path"));
22151
22328
  function getDraftsDir() {
22152
22329
  return path3.join(getConfigDir(), "drafts");
22153
22330
  }
22331
+ function encodeDraftId(draftId) {
22332
+ return Buffer.from(draftId, "utf-8").toString("base64url");
22333
+ }
22154
22334
  function getDraftPath(draftId) {
22155
- const safeName = draftId.replace(/[^a-zA-Z0-9_-]/g, "_");
22156
- return path3.join(getDraftsDir(), `${safeName}.json`);
22335
+ return path3.join(getDraftsDir(), `${encodeDraftId(draftId)}.json`);
22157
22336
  }
22158
22337
  function writeDraft(draft) {
22159
22338
  const dir = getDraftsDir();
@@ -22318,8 +22497,10 @@ function registerBuildCommand(parent, getContext2) {
22318
22497
  // src/commands/tool/run.ts
22319
22498
  var fs6 = __toESM(require("fs"));
22320
22499
  var path5 = __toESM(require("path"));
22500
+ var crypto2 = __toESM(require("crypto"));
22501
+ var import_shared4 = __toESM(require_dist2());
22321
22502
  function registerRunCommand(parent, getContext2) {
22322
- 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(
22503
+ 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(
22323
22504
  "--file <key=path...>",
22324
22505
  "File references",
22325
22506
  (v, arr) => {
@@ -22329,8 +22510,13 @@ function registerRunCommand(parent, getContext2) {
22329
22510
  []
22330
22511
  ).option("--include-step-results", "Include raw step results").option("--include-config", "Include full tool config").action(async (opts) => {
22331
22512
  const { config, client } = getContext2();
22332
- if (!opts.draft && !opts.tool) {
22333
- error("Provide --draft or --tool");
22513
+ const selectors = [opts.tool, opts.draft, opts.config, opts.configFile].filter(Boolean);
22514
+ if (selectors.length === 0) {
22515
+ error("Provide one of --tool, --draft, --config, or --config-file");
22516
+ process.exit(1);
22517
+ }
22518
+ if (selectors.length > 1) {
22519
+ error("Only one of --tool, --draft, --config, or --config-file can be used");
22334
22520
  process.exit(1);
22335
22521
  }
22336
22522
  const filePayloads = await parseFileFlags(opts.file, client);
@@ -22344,32 +22530,67 @@ function registerRunCommand(parent, getContext2) {
22344
22530
  payload = fileResult.resolved;
22345
22531
  }
22346
22532
  let result;
22347
- const toolLabel = opts.tool || opts.draft;
22533
+ const toolLabel = opts.tool || opts.draft || "inline-config";
22534
+ const traceId = crypto2.randomUUID();
22348
22535
  const spin = spinner(`Running ${c.bold}${toolLabel}${c.reset}...`);
22349
- if (opts.tool) {
22536
+ const logSub = await client.subscribeToLogsSSE({
22537
+ traceId,
22538
+ onLog: (log) => spin.log(`${c.dim}${log.message}${c.reset}`)
22539
+ }).catch(() => ({ unsubscribe: () => {
22540
+ } }));
22541
+ const runToolConfig = async (toolConfig) => {
22350
22542
  try {
22351
- result = await client.runTool({ toolId: opts.tool, payload });
22543
+ const res = await client.runToolConfig({
22544
+ tool: toolConfig,
22545
+ payload,
22546
+ options: { requestSource: import_shared4.RequestSource.CLI },
22547
+ traceId
22548
+ });
22549
+ logSub.unsubscribe();
22352
22550
  spin.stop();
22551
+ return res;
22353
22552
  } catch (err) {
22553
+ logSub.unsubscribe();
22354
22554
  spin.stop();
22355
22555
  error(err.message);
22356
22556
  process.exit(1);
22357
22557
  }
22358
- } else {
22359
- const draft = readDraft(opts.draft);
22360
- if (!draft) {
22558
+ };
22559
+ if (opts.tool) {
22560
+ try {
22561
+ result = await client.runTool({
22562
+ toolId: opts.tool,
22563
+ payload,
22564
+ options: { requestSource: import_shared4.RequestSource.CLI, traceId }
22565
+ });
22566
+ logSub.unsubscribe();
22361
22567
  spin.stop();
22362
- error(`Draft not found: ${opts.draft}`);
22568
+ } catch (err) {
22569
+ logSub.unsubscribe();
22570
+ spin.stop();
22571
+ error(err.message);
22363
22572
  process.exit(1);
22364
22573
  }
22574
+ } else if (opts.config || opts.configFile) {
22575
+ let toolConfig;
22365
22576
  try {
22366
- result = await client.runToolConfig({ tool: draft.config, payload });
22367
- spin.stop();
22577
+ toolConfig = opts.configFile ? JSON.parse(fs6.readFileSync(opts.configFile, "utf-8")) : JSON.parse(opts.config);
22368
22578
  } catch (err) {
22579
+ logSub.unsubscribe();
22369
22580
  spin.stop();
22370
- error(err.message);
22581
+ error(`Invalid tool config JSON: ${err.message}`);
22371
22582
  process.exit(1);
22372
22583
  }
22584
+ result = await runToolConfig(toolConfig);
22585
+ } else {
22586
+ const draft = readDraft(opts.draft);
22587
+ if (!draft) {
22588
+ logSub.unsubscribe();
22589
+ spin.stop();
22590
+ error(`Draft not found: ${opts.draft}`);
22591
+ process.exit(1);
22592
+ }
22593
+ result = await runToolConfig(draft.config);
22373
22594
  }
22374
22595
  const out = {
22375
22596
  success: result.success,
@@ -22382,7 +22603,7 @@ function registerRunCommand(parent, getContext2) {
22382
22603
  if (config.output.mode === "stdout+file") {
22383
22604
  const outDir = path5.resolve(config.output.directory);
22384
22605
  if (!fs6.existsSync(outDir)) fs6.mkdirSync(outDir, { recursive: true });
22385
- const rawId = opts.tool || opts.draft;
22606
+ const rawId = opts.tool || opts.draft || "inline-config";
22386
22607
  const safeId = path5.basename(rawId).replace(/[^a-zA-Z0-9_-]/g, "_");
22387
22608
  const filename = `${safeId}-${Date.now()}.json`;
22388
22609
  fs6.writeFileSync(path5.join(outDir, filename), JSON.stringify(out, null, 2));
@@ -22393,11 +22614,13 @@ function registerRunCommand(parent, getContext2) {
22393
22614
 
22394
22615
  // src/commands/tool/edit.ts
22395
22616
  var fs7 = __toESM(require("fs"));
22396
- var import_shared4 = __toESM(require_dist2());
22617
+ var crypto3 = __toESM(require("crypto"));
22618
+ var import_shared5 = __toESM(require_dist2());
22619
+ var import_shared6 = __toESM(require_dist2());
22397
22620
  var jsonpatch = __toESM(require("fast-json-patch"));
22398
22621
  function registerEditCommand(parent, getContext2) {
22399
22622
  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) => {
22400
- const { config, client } = getContext2();
22623
+ const { client } = getContext2();
22401
22624
  if (!opts.draft && !opts.tool) {
22402
22625
  error("Provide --draft or --tool");
22403
22626
  process.exit(1);
@@ -22443,7 +22666,7 @@ function registerEditCommand(parent, getContext2) {
22443
22666
  try {
22444
22667
  const copy = JSON.parse(JSON.stringify(originalConfig));
22445
22668
  const result = jsonpatch.applyPatch(copy, patches, true, true);
22446
- patchedConfig = (0, import_shared4.normalizeToolSchemas)(result.newDocument || copy);
22669
+ patchedConfig = (0, import_shared6.normalizeToolSchemas)(result.newDocument || copy);
22447
22670
  } catch (err) {
22448
22671
  error(`Patch failed: ${err.message}`);
22449
22672
  process.exit(1);
@@ -22459,23 +22682,15 @@ function registerEditCommand(parent, getContext2) {
22459
22682
  console.log(renderDiffs(diffs));
22460
22683
  console.log("");
22461
22684
  }
22462
- const autoAccept = process.argv.includes("--yes") || process.argv.includes("-y") || config.policies.editTool === "auto_accept";
22463
- if (!autoAccept) {
22464
- const accepted = await confirm("Accept changes?");
22465
- if (!accepted) {
22466
- output({ success: false, rejected: true, message: "Changes rejected" });
22467
- process.exit(1);
22468
- }
22469
- }
22470
22685
  const draft = {
22471
22686
  draftId: workingDraftId,
22472
22687
  config: {
22473
22688
  ...patchedConfig,
22474
- instruction: originalConfig.instruction || patchedConfig.instruction,
22689
+ instruction: patchedConfig.instruction ?? originalConfig.instruction,
22475
22690
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
22476
22691
  },
22477
22692
  systemIds: patchedConfig.systemIds || [],
22478
- instruction: patchedConfig.instruction || "",
22693
+ instruction: patchedConfig.instruction ?? "",
22479
22694
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
22480
22695
  };
22481
22696
  writeDraft(draft);
@@ -22487,9 +22702,21 @@ function registerEditCommand(parent, getContext2) {
22487
22702
  error(`Invalid --payload JSON: ${err.message}`);
22488
22703
  process.exit(1);
22489
22704
  }
22705
+ const traceId = crypto3.randomUUID();
22490
22706
  const spin = spinner("Running test...");
22707
+ const logSub = await client.subscribeToLogsSSE({
22708
+ traceId,
22709
+ onLog: (log) => spin.log(`${c.dim}${log.message}${c.reset}`)
22710
+ }).catch(() => ({ unsubscribe: () => {
22711
+ } }));
22491
22712
  try {
22492
- const testResult = await client.runToolConfig({ tool: draft.config, payload });
22713
+ const testResult = await client.runToolConfig({
22714
+ tool: draft.config,
22715
+ payload,
22716
+ options: { requestSource: import_shared5.RequestSource.CLI },
22717
+ traceId
22718
+ });
22719
+ logSub.unsubscribe();
22493
22720
  spin.stop();
22494
22721
  if (testResult.success) {
22495
22722
  success("Test passed");
@@ -22511,6 +22738,7 @@ function registerEditCommand(parent, getContext2) {
22511
22738
  output(testResult.data);
22512
22739
  }
22513
22740
  } catch (err) {
22741
+ logSub.unsubscribe();
22514
22742
  spin.stop();
22515
22743
  error(`Test error: ${err.message}`);
22516
22744
  output({
@@ -22541,8 +22769,8 @@ function registerSaveCommand(parent, getContext2) {
22541
22769
  process.exit(1);
22542
22770
  }
22543
22771
  const toolId = opts.id || draft.config.id;
22772
+ const spin = spinner(`Saving tool ${c.bold}${toolId}${c.reset}...`);
22544
22773
  try {
22545
- const spin = spinner(`Saving tool ${c.bold}${toolId}${c.reset}...`);
22546
22774
  const saved = await client.upsertWorkflow(toolId, {
22547
22775
  ...draft.config,
22548
22776
  id: toolId,
@@ -22564,6 +22792,7 @@ function registerSaveCommand(parent, getContext2) {
22564
22792
  console.log("");
22565
22793
  }
22566
22794
  } catch (err) {
22795
+ spin.stop();
22567
22796
  error(err.message);
22568
22797
  process.exit(1);
22569
22798
  }
@@ -22602,7 +22831,7 @@ function registerFindCommand(parent, getContext2) {
22602
22831
  output({ success: true, tool });
22603
22832
  return;
22604
22833
  }
22605
- const searchQuery = query || "*";
22834
+ const searchQuery = (query || "").trim() || "*";
22606
22835
  if (searchQuery === "*") {
22607
22836
  const { items } = await client.listWorkflows(100);
22608
22837
  const tools = items.filter((t) => !t.archived).map((t) => ({
@@ -22641,7 +22870,8 @@ function registerToolCommands(program2, getContext2) {
22641
22870
 
22642
22871
  // src/commands/system/create.ts
22643
22872
  var fs8 = __toESM(require("fs"));
22644
- var import_shared5 = __toESM(require_dist2());
22873
+ var import_commander = require("commander");
22874
+ var import_shared7 = __toESM(require_dist2());
22645
22875
  async function collectSensitiveCredentials(fields) {
22646
22876
  const creds = {};
22647
22877
  for (const field of fields) {
@@ -22659,12 +22889,21 @@ async function collectSensitiveCredentials(fields) {
22659
22889
  return creds;
22660
22890
  }
22661
22891
  function registerCreateCommand(parent, getContext2) {
22662
- 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) => {
22892
+ 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(
22893
+ new import_commander.Option("--env <environment>", "Environment: dev or prod (default: prod)").choices([
22894
+ "dev",
22895
+ "prod"
22896
+ ])
22897
+ ).action(async (opts) => {
22663
22898
  const { client } = getContext2();
22664
22899
  let systemInput;
22665
22900
  if (opts.config) {
22666
22901
  try {
22667
- systemInput = JSON.parse(fs8.readFileSync(opts.config, "utf-8"));
22902
+ const parsed = JSON.parse(fs8.readFileSync(opts.config, "utf-8"));
22903
+ if (opts.env === "dev" || opts.env === "prod") {
22904
+ parsed.environment = opts.env;
22905
+ }
22906
+ systemInput = parsed;
22668
22907
  } catch (err) {
22669
22908
  error(`Invalid config file: ${err.message}`);
22670
22909
  process.exit(1);
@@ -22684,14 +22923,15 @@ function registerCreateCommand(parent, getContext2) {
22684
22923
  name: opts.name,
22685
22924
  url: opts.url,
22686
22925
  specificInstructions: opts.instructions,
22687
- credentials
22926
+ credentials,
22927
+ environment: opts.env === "dev" || opts.env === "prod" ? opts.env : void 0
22688
22928
  };
22689
22929
  }
22690
22930
  if (opts.template) {
22691
- const template = import_shared5.systems[opts.template];
22931
+ const template = import_shared7.systems[opts.template];
22692
22932
  if (!template) {
22693
22933
  error(
22694
- `Template not found: ${opts.template}. Available: ${Object.keys(import_shared5.systems).join(", ")}`
22934
+ `Template not found: ${opts.template}. Available: ${Object.keys(import_shared7.systems).join(", ")}`
22695
22935
  );
22696
22936
  process.exit(1);
22697
22937
  }
@@ -22703,10 +22943,10 @@ function registerCreateCommand(parent, getContext2) {
22703
22943
  if (template.oauth.client_id) oauthCreds.client_id = template.oauth.client_id;
22704
22944
  }
22705
22945
  systemInput = {
22946
+ ...systemInput,
22706
22947
  name: systemInput.name || template.name,
22707
- url: template.apiUrl,
22948
+ url: systemInput.url || template.apiUrl,
22708
22949
  templateName: opts.template,
22709
- ...systemInput,
22710
22950
  credentials: { ...oauthCreds, ...systemInput.credentials }
22711
22951
  };
22712
22952
  }
@@ -22754,8 +22994,11 @@ function registerCreateCommand(parent, getContext2) {
22754
22994
  }
22755
22995
 
22756
22996
  // src/commands/system/edit.ts
22997
+ var import_commander2 = require("commander");
22757
22998
  function registerEditCommand2(parent, getContext2) {
22758
- 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) => {
22999
+ 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(
23000
+ new import_commander2.Option("--env <environment>", "Environment: dev or prod").choices(["dev", "prod"])
23001
+ ).action(async (opts) => {
22759
23002
  const { client } = getContext2();
22760
23003
  const patchPayload = { id: opts.id };
22761
23004
  if (opts.name) patchPayload.name = opts.name;
@@ -22787,8 +23030,9 @@ function registerEditCommand2(parent, getContext2) {
22787
23030
  patchPayload.credentials = { ...patchPayload.credentials, ...creds };
22788
23031
  }
22789
23032
  try {
23033
+ const envOption = opts.env === "dev" || opts.env === "prod" ? { environment: opts.env } : void 0;
22790
23034
  const spin = spinner(`Updating system ${c.bold}${opts.id}${c.reset}...`);
22791
- const existing = await client.getSystem(opts.id);
23035
+ const existing = await client.getSystem(opts.id, envOption);
22792
23036
  if (!existing) {
22793
23037
  spin.stop();
22794
23038
  error(`System not found: ${opts.id}`);
@@ -22797,7 +23041,7 @@ function registerEditCommand2(parent, getContext2) {
22797
23041
  if (patchPayload.credentials && existing.credentials) {
22798
23042
  patchPayload.credentials = { ...existing.credentials, ...patchPayload.credentials };
22799
23043
  }
22800
- const result = await client.updateSystem(opts.id, patchPayload);
23044
+ const result = await client.updateSystem(opts.id, patchPayload, envOption);
22801
23045
  if (opts.scrapeUrl) {
22802
23046
  try {
22803
23047
  const keywords = opts.scrapeKeywords?.split(" ").filter(Boolean);
@@ -22805,7 +23049,9 @@ function registerEditCommand2(parent, getContext2) {
22805
23049
  url: opts.scrapeUrl,
22806
23050
  keywords
22807
23051
  });
22808
- } catch {
23052
+ } catch (scrapeErr) {
23053
+ const errMsg = scrapeErr instanceof Error ? scrapeErr.message : String(scrapeErr || "Unknown error");
23054
+ warn(`Documentation scrape failed for ${opts.scrapeUrl}: ${errMsg}`);
22809
23055
  }
22810
23056
  }
22811
23057
  spin.stop();
@@ -22822,45 +23068,52 @@ function registerEditCommand2(parent, getContext2) {
22822
23068
  }
22823
23069
 
22824
23070
  // src/commands/system/find.ts
22825
- var import_shared6 = __toESM(require_dist2());
23071
+ var import_commander3 = require("commander");
23072
+ var import_shared8 = __toESM(require_dist2());
22826
23073
  function filterSystemFields(system) {
22827
23074
  const credentialKeys = Object.keys(system.credentials || {});
22828
23075
  return {
22829
23076
  id: system.id,
22830
23077
  name: system.name,
22831
23078
  url: system.url,
23079
+ environment: system.environment,
22832
23080
  specificInstructions: system.specificInstructions,
22833
23081
  credentialPlaceholders: credentialKeys.map((k) => `<<${system.id}_${k}>>`)
22834
23082
  };
22835
23083
  }
22836
23084
  function registerFindCommand2(parent, getContext2) {
22837
- parent.command("list").description("List all systems").action(async () => {
23085
+ parent.command("list").description("List all systems").option("--mode <mode>", "Filter by environment: dev, prod, or all (default: all)").action(async (opts) => {
22838
23086
  const { client } = getContext2();
22839
23087
  try {
22840
- const { items } = await client.listSystems(100);
23088
+ const mode = opts.mode === "dev" || opts.mode === "prod" ? opts.mode : "all";
23089
+ const { items } = await client.listSystems(100, 1, { mode });
22841
23090
  table(
22842
23091
  items.map((s) => ({
22843
23092
  id: s.id,
22844
23093
  name: s.name || "",
23094
+ env: s.environment || "prod",
22845
23095
  url: (s.url || "").slice(0, 50)
22846
23096
  })),
22847
- ["id", "name", "url"]
23097
+ ["id", "name", "env", "url"]
22848
23098
  );
22849
23099
  } catch (err) {
22850
23100
  error(err.message);
22851
23101
  process.exit(1);
22852
23102
  }
22853
23103
  });
22854
- parent.command("find [query]").description("Find systems by query or exact ID").option("--id <exactId>", "Exact system ID lookup").action(async (query, opts) => {
23104
+ parent.command("find [query]").description("Find systems by query or exact ID").option("--id <exactId>", "Exact system ID lookup").addOption(
23105
+ new import_commander3.Option("--env <environment>", "Environment: dev or prod").choices(["dev", "prod"])
23106
+ ).action(async (query, opts) => {
22855
23107
  const { client } = getContext2();
22856
23108
  try {
22857
23109
  if (opts.id) {
22858
- const system = await client.getSystem(opts.id);
23110
+ const envOption = opts.env === "dev" || opts.env === "prod" ? { environment: opts.env } : void 0;
23111
+ const system = await client.getSystem(opts.id, envOption);
22859
23112
  if (!system) {
22860
23113
  error(`System not found: ${opts.id}`);
22861
23114
  process.exit(1);
22862
23115
  }
22863
- const templateMatch = (0, import_shared6.findTemplateForSystem)(system);
23116
+ const templateMatch = (0, import_shared8.findTemplateForSystem)(system);
22864
23117
  output({
22865
23118
  success: true,
22866
23119
  system: filterSystemFields(system),
@@ -22868,8 +23121,9 @@ function registerFindCommand2(parent, getContext2) {
22868
23121
  });
22869
23122
  return;
22870
23123
  }
23124
+ const listMode = opts.env ? { mode: opts.env } : void 0;
22871
23125
  const rawQuery = (query || "*").trim();
22872
- const { items } = await client.listSystems(100);
23126
+ const { items } = await client.listSystems(100, 1, listMode);
22873
23127
  if (rawQuery === "*") {
22874
23128
  output({
22875
23129
  success: true,
@@ -22894,16 +23148,8 @@ function registerFindCommand2(parent, getContext2) {
22894
23148
  }
22895
23149
 
22896
23150
  // src/commands/system/call.ts
22897
- var import_shared7 = __toESM(require_dist2());
22898
- function shouldAutoExecute(policy, method, url) {
22899
- if (policy === "run_everything") return true;
22900
- if (policy === "ask_every_time") return false;
22901
- if (policy === "run_gets_only") {
22902
- const protocol = (0, import_shared7.getConnectionProtocol)(url);
22903
- return protocol === "http" && method.toUpperCase() === "GET";
22904
- }
22905
- return false;
22906
- }
23151
+ var import_commander4 = require("commander");
23152
+ var import_shared9 = __toESM(require_dist2());
22907
23153
  function registerCallCommand(parent, getContext2) {
22908
23154
  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(
22909
23155
  "--file <key=path...>",
@@ -22913,47 +23159,39 @@ function registerCallCommand(parent, getContext2) {
22913
23159
  return arr;
22914
23160
  },
22915
23161
  []
23162
+ ).addOption(
23163
+ new import_commander4.Option("--env <environment>", "Environment: dev or prod").choices(["dev", "prod"])
22916
23164
  ).action(async (opts) => {
22917
- const { config, client } = getContext2();
23165
+ const { client } = getContext2();
22918
23166
  const method = opts.method || "GET";
22919
23167
  const filePayloads = await parseFileFlags(opts.file, client);
22920
23168
  let body = opts.body;
22921
23169
  if (body && Object.keys(filePayloads).length > 0) {
22922
23170
  try {
22923
23171
  let parsed = JSON.parse(body);
22924
- for (const [k, v] of Object.entries(parsed)) {
22925
- if (typeof v === "string" && v.startsWith("file::")) {
22926
- const key = v.slice(6);
22927
- if (key in filePayloads) parsed[k] = filePayloads[key];
23172
+ const resolveFileRefs = (obj) => {
23173
+ if (typeof obj === "string" && obj.startsWith("file::")) {
23174
+ const key = obj.slice(6);
23175
+ if (key in filePayloads) return filePayloads[key];
23176
+ error(
23177
+ `Unresolved file reference: file::${key}. Available: ${Object.keys(filePayloads).join(", ") || "(none)"}`
23178
+ );
23179
+ process.exit(1);
22928
23180
  }
22929
- }
23181
+ if (Array.isArray(obj)) return obj.map(resolveFileRefs);
23182
+ if (obj && typeof obj === "object") {
23183
+ const result = {};
23184
+ for (const [k, v] of Object.entries(obj)) {
23185
+ result[k] = resolveFileRefs(v);
23186
+ }
23187
+ return result;
23188
+ }
23189
+ return obj;
23190
+ };
23191
+ parsed = resolveFileRefs(parsed);
22930
23192
  body = JSON.stringify(parsed);
22931
- } catch {
22932
- }
22933
- }
22934
- const autoExec = process.argv.includes("--yes") || process.argv.includes("-y") || shouldAutoExecute(config.policies.callSystem, method, opts.url);
22935
- if (!autoExec) {
22936
- const methodColors = {
22937
- GET: c.green,
22938
- POST: c.yellow,
22939
- PUT: c.blue,
22940
- PATCH: c.magenta,
22941
- DELETE: c.red
22942
- };
22943
- const mc = methodColors[method.toUpperCase()] || c.white;
22944
- console.log("");
22945
- console.log(` ${mc}${c.bold}${method.toUpperCase()}${c.reset} ${opts.url}`);
22946
- if (opts.systemId) console.log(` ${c.dim}system:${c.reset} ${opts.systemId}`);
22947
- if (opts.headers) console.log(` ${c.dim}headers:${c.reset} ${opts.headers}`);
22948
- if (body) {
22949
- const preview = body.length > 200 ? body.slice(0, 200) + `${c.dim}...${c.reset}` : body;
22950
- console.log(` ${c.dim}body:${c.reset} ${preview}`);
22951
- }
22952
- console.log("");
22953
- const accepted = await confirm("Execute this request?");
22954
- if (!accepted) {
22955
- output({ success: false, cancelled: true, message: "Request cancelled" });
22956
- process.exit(0);
23193
+ } catch (err) {
23194
+ if (err.message?.startsWith("Unresolved file reference")) throw err;
22957
23195
  }
22958
23196
  }
22959
23197
  let headers;
@@ -22977,11 +23215,12 @@ function registerCallCommand(parent, getContext2) {
22977
23215
  }
22978
23216
  };
22979
23217
  try {
22980
- const result = await client.executeStep({ step, payload: {} });
23218
+ const mode = opts.env === "dev" || opts.env === "prod" ? opts.env : void 0;
23219
+ const result = await client.executeStep({ step, payload: {}, mode });
22981
23220
  const responseData = result.data?.data !== void 0 ? result.data.data : result.data;
22982
23221
  output({
22983
23222
  success: result.success,
22984
- protocol: (0, import_shared7.getConnectionProtocol)(opts.url),
23223
+ protocol: (0, import_shared9.getConnectionProtocol)(opts.url),
22985
23224
  data: responseData,
22986
23225
  ...result.error ? { error: result.error } : {}
22987
23226
  });
@@ -22995,7 +23234,7 @@ function registerCallCommand(parent, getContext2) {
22995
23234
 
22996
23235
  // src/commands/system/docs.ts
22997
23236
  function registerDocsCommand(parent, getContext2) {
22998
- parent.command("docs").description("Search system documentation").requiredOption("--system-id <id>", "System ID").requiredOption("--keywords <keywords>", "Search keywords").action(async (opts) => {
23237
+ 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) => {
22999
23238
  const { client } = getContext2();
23000
23239
  try {
23001
23240
  const result = await client.searchSystemDocumentation(opts.systemId, opts.keywords);
@@ -23041,13 +23280,13 @@ function registerDocsCommand(parent, getContext2) {
23041
23280
  }
23042
23281
 
23043
23282
  // src/commands/system/oauth.ts
23044
- var import_node_child_process = require("child_process");
23045
- var import_shared8 = __toESM(require_dist2());
23283
+ var import_node_child_process2 = require("child_process");
23284
+ var import_shared10 = __toESM(require_dist2());
23046
23285
  function openBrowser(url) {
23047
23286
  const platform = process.platform;
23048
23287
  const cmd = platform === "darwin" ? "open" : platform === "win32" ? "cmd" : "xdg-open";
23049
23288
  const args = platform === "win32" ? ["/c", "start", "", url] : [url];
23050
- (0, import_node_child_process.spawn)(cmd, args, { detached: true, stdio: "ignore" }).unref();
23289
+ (0, import_node_child_process2.spawn)(cmd, args, { detached: true, stdio: "ignore" }).unref();
23051
23290
  }
23052
23291
  async function pollForTokens(client, systemId, originalToken, timeoutMs = 3e5, intervalMs = 2e3) {
23053
23292
  const start = Date.now();
@@ -23078,7 +23317,7 @@ function registerOAuthCommand(parent, getContext2) {
23078
23317
  error(err.message);
23079
23318
  process.exit(1);
23080
23319
  }
23081
- const templateMatch = (0, import_shared8.findTemplateForSystem)(system);
23320
+ const templateMatch = (0, import_shared10.findTemplateForSystem)(system);
23082
23321
  const templateOAuth = templateMatch?.template?.oauth;
23083
23322
  const clientId = system.credentials?.client_id ?? templateOAuth?.client_id;
23084
23323
  const authUrl = opts.authUrl ?? system.credentials?.auth_url ?? templateOAuth?.authUrl;
@@ -23156,7 +23395,7 @@ function registerOAuthCommand(parent, getContext2) {
23156
23395
  error(`Failed to get OAuth encryption secret: ${err.message}`);
23157
23396
  process.exit(1);
23158
23397
  }
23159
- const encryptedApiKey = (0, import_shared8.encryptCliApiKey)(config.apiKey, opts.systemId, encryptionSecret);
23398
+ const encryptedApiKey = (0, import_shared10.encryptCliApiKey)(config.apiKey, opts.systemId, encryptionSecret);
23160
23399
  const redirectUri = `${config.webEndpoint.replace(/\/$/, "")}/api/auth/callback`;
23161
23400
  const state = {
23162
23401
  systemId: opts.systemId,
@@ -23207,12 +23446,12 @@ function registerSystemCommands(program2, getContext2) {
23207
23446
 
23208
23447
  // src/commands/run/list.ts
23209
23448
  function registerListCommand(parent, getContext2) {
23210
- parent.command("list").description("List recent runs").option("--tool <id>", "Filter by tool ID").option("--status <status>", "Filter by status (running, success, failed, aborted)").option("--source <sources>", "Comma-separated request sources").option("--user <userId>", "Filter by user ID").option("--system-id <id>", "Filter by system ID").option("--limit <n>", "Max results", "10").option("--offset <n>", "Skip first N results", "0").option("--search <text>", "Full-text search").action(async (opts) => {
23449
+ parent.command("list").description("List recent runs").option("--tool <id>", "Filter by tool ID").option("--status <status>", "Filter by status (running, success, failed, aborted)").option("--source <sources>", "Comma-separated request sources").option("--user <userId>", "Filter by user ID").option("--system-id <id>", "Filter by system ID").option("--limit <n>", "Max results", "10").option("--offset <n>", "Skip first N results", "0").action(async (opts) => {
23211
23450
  const { client } = getContext2();
23212
23451
  try {
23213
23452
  const limit = Math.min(parseInt(opts.limit, 10) || 10, 50);
23214
23453
  const offset = parseInt(opts.offset, 10) || 0;
23215
- const page = Math.floor(offset / limit) + 1;
23454
+ const page = Math.ceil((offset + 1) / limit);
23216
23455
  const requestSources = opts.source?.split(",").filter(Boolean);
23217
23456
  const result = await client.listRuns({
23218
23457
  toolId: opts.tool,
@@ -23295,109 +23534,6 @@ function registerRunCommands(program2, getContext2) {
23295
23534
  registerGetCommand(run, getContext2);
23296
23535
  }
23297
23536
 
23298
- // src/version.ts
23299
- var import_node_child_process2 = require("child_process");
23300
- var import_node_util = require("util");
23301
-
23302
- // package.json
23303
- var package_default = {
23304
- name: "@superglue/cli",
23305
- version: "1.0.0",
23306
- bin: {
23307
- sg: "./dist/cli.js"
23308
- },
23309
- files: [
23310
- "dist/",
23311
- "skills/",
23312
- "skills.md"
23313
- ],
23314
- dependencies: {
23315
- commander: "^13.0.0",
23316
- "fast-json-patch": "^3.1.1"
23317
- },
23318
- devDependencies: {
23319
- "@superglue/shared": "file:../shared",
23320
- "@types/node": "^20.0.0",
23321
- tsup: "^8.0.0",
23322
- typescript: "^5.0.0"
23323
- },
23324
- scripts: {
23325
- build: "tsup && cp -r skills dist/ 2>/dev/null || true",
23326
- dev: "tsup --watch",
23327
- "type-check": "tsc --noEmit",
23328
- prepublishOnly: "npm run build"
23329
- },
23330
- publishConfig: {
23331
- access: "public"
23332
- }
23333
- };
23334
-
23335
- // src/version.ts
23336
- var execAsync = (0, import_node_util.promisify)(import_node_child_process2.exec);
23337
- var CLI_VERSION = package_default.version;
23338
- function compareVersions(a, b) {
23339
- const partsA = a.split(".").map(Number);
23340
- const partsB = b.split(".").map(Number);
23341
- for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {
23342
- const numA = partsA[i] || 0;
23343
- const numB = partsB[i] || 0;
23344
- if (numA < numB) return -1;
23345
- if (numA > numB) return 1;
23346
- }
23347
- return 0;
23348
- }
23349
- async function checkVersionCompatibility(endpoint) {
23350
- try {
23351
- const healthUrl = `${endpoint.replace(/\/$/, "")}/v1/health`;
23352
- const response = await fetch(healthUrl, { signal: AbortSignal.timeout(3e3) });
23353
- if (!response.ok) return;
23354
- const health = await response.json();
23355
- if (!health.minCliVersion) return;
23356
- if (compareVersions(CLI_VERSION, health.minCliVersion) < 0) {
23357
- console.error("");
23358
- console.error(`${c.yellow}${c.bold}\u26A0 CLI version ${CLI_VERSION} is outdated.${c.reset}`);
23359
- console.error(
23360
- `${c.yellow} Server requires at least v${health.minCliVersion}. Run: ${c.bold}sg update${c.reset}`
23361
- );
23362
- console.error("");
23363
- }
23364
- } catch {
23365
- }
23366
- }
23367
- async function getLatestNpmVersion() {
23368
- try {
23369
- const response = await fetch("https://registry.npmjs.org/@superglue/cli/latest", {
23370
- signal: AbortSignal.timeout(5e3)
23371
- });
23372
- if (!response.ok) return null;
23373
- const data = await response.json();
23374
- return data.version || null;
23375
- } catch {
23376
- return null;
23377
- }
23378
- }
23379
- async function updateCli() {
23380
- const latestVersion = await getLatestNpmVersion();
23381
- if (!latestVersion) {
23382
- return { success: false, message: "Could not fetch latest version from npm" };
23383
- }
23384
- if (compareVersions(CLI_VERSION, latestVersion) >= 0) {
23385
- return { success: true, message: `Already on latest version (${CLI_VERSION})` };
23386
- }
23387
- try {
23388
- await execAsync("npm install -g @superglue/cli@latest");
23389
- return {
23390
- success: true,
23391
- message: `Updated from ${CLI_VERSION} to ${latestVersion}`
23392
- };
23393
- } catch (err) {
23394
- return {
23395
- success: false,
23396
- message: `Update failed: ${err.message}. Try manually: npm install -g @superglue/cli@latest`
23397
- };
23398
- }
23399
- }
23400
-
23401
23537
  // src/commands/update.ts
23402
23538
  function registerUpdateCommand(program2) {
23403
23539
  program2.command("update").description("Update the superglue CLI to the latest version").option("--check", "Only check for updates, don't install").action(async (opts) => {
@@ -23435,45 +23571,44 @@ function registerUpdateCommand(program2) {
23435
23571
  }
23436
23572
 
23437
23573
  // src/cli.ts
23438
- var program = new import_commander.Command();
23439
- 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(
23574
+ var program = new import_commander5.Command();
23575
+ 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(
23440
23576
  "after",
23441
23577
  `
23442
23578
  All Commands:
23443
- sg init Set up CLI configuration
23579
+ sg init Set up CLI configuration
23444
23580
 
23445
- sg tool build --config <file> Build a tool from a JSON config file
23446
- sg tool build --id <id> --instruction <t> Build a tool from flags (requires --steps <file>)
23447
- sg tool run --draft <id> [--payload <json>] Run a draft tool
23448
- sg tool run --tool <id> [--payload <json>] Run a saved tool
23449
- sg tool edit --tool <id> --patches <json> Edit a tool via JSON Patch operations
23450
- sg tool edit --draft <id> --patches <json> Edit a draft via JSON Patch operations
23451
- sg tool save <id> Save a draft tool to the server
23452
- sg tool list List all saved tools (IDs + instructions)
23453
- sg tool find [query] Search tools by keyword
23454
- sg tool find --id <id> Get full config of a specific tool
23581
+ sg tool build --config <file> Build a tool from a JSON config
23582
+ sg tool build --id <id> --instruction <text> Build a tool from flags (requires --steps)
23583
+ sg tool run --tool <id> [--payload <json>] Run a saved tool
23584
+ sg tool run --draft <id> [--payload <json>] Run a draft tool
23585
+ sg tool edit --tool <id> --patches <json> Edit a tool via JSON Patch
23586
+ sg tool edit --draft <id> --patches <json> Edit a draft via JSON Patch
23587
+ sg tool save --draft <id> Save a draft to the server
23588
+ sg tool list List all saved tools
23589
+ sg tool find [query] Search tools by keyword
23590
+ sg tool find --id <id> Get full config of a tool
23455
23591
 
23456
- sg system create --config <file> Create a system from a JSON config file
23457
- sg system create --id <id> --url <url> Create a system from flags
23458
- sg system edit <id> Edit a system's configuration
23459
- sg system list List all systems
23460
- sg system find [query] Search systems by keyword
23461
- sg system find --id <id> Get full config of a specific system
23462
- sg system call --url <url> [--method GET] Call an API/DB/file server with credential injection
23463
- sg system docs <id> View system documentation
23464
- sg system oauth <id> Authenticate a system via OAuth
23592
+ sg system create --config <file> Create a system from JSON config
23593
+ sg system create --id <id> --url <url> Create a system from flags
23594
+ sg system edit --id <id> Edit a system's configuration
23595
+ sg system list List all systems
23596
+ sg system find [query] Search systems by keyword
23597
+ sg system find --id <id> Get full config of a system
23598
+ sg system call --url <url> [--method GET] Call an API, database, or file server
23599
+ sg system search-docs --system-id <id> -k <kw> Search system documentation
23600
+ sg system oauth --system-id <id> --scopes <s> Authenticate a system via OAuth
23465
23601
 
23466
- sg run list [toolId] List execution runs, optionally filtered by tool
23467
- sg run get <runId> Get details of a specific run
23602
+ sg run list [toolId] List runs, optionally filtered by tool
23603
+ sg run get <runId> Get details of a specific run
23468
23604
 
23469
- sg update Update CLI to latest version
23470
- sg update --check Check for available updates
23605
+ sg update Update CLI to latest version
23606
+ sg update --check Check for available updates
23471
23607
 
23472
23608
  Global Flags:
23473
- --api-key <key> Override API key from config
23474
- --endpoint <url> Override API endpoint from config
23475
- --json Force JSON output (default in non-TTY)
23476
- -y, --yes Auto-accept all confirmations
23609
+ --api-key <key> Override API key from config
23610
+ --endpoint <url> Override API endpoint from config
23611
+ --json Force JSON output (default in non-TTY)
23477
23612
  `
23478
23613
  );
23479
23614
  var getContext = () => {
@@ -23489,7 +23624,7 @@ registerSystemCommands(program, getContext);
23489
23624
  registerRunCommands(program, getContext);
23490
23625
  var commandsRequiringServer = ["tool", "system", "run"];
23491
23626
  var globalFlagsWithValues = ["--api-key", "--endpoint"];
23492
- var globalFlagsNoValue = ["--json", "-y", "--yes", "-h", "--help", "-V", "--version"];
23627
+ var globalFlagsNoValue = ["--json", "-h", "--help", "-V", "--version"];
23493
23628
  function findSubcommand(argv) {
23494
23629
  let i = 2;
23495
23630
  while (i < argv.length) {
@@ -23506,12 +23641,22 @@ function findSubcommand(argv) {
23506
23641
  }
23507
23642
  return void 0;
23508
23643
  }
23644
+ function extractFlagValue(argv, flag) {
23645
+ for (let i = 0; i < argv.length; i++) {
23646
+ const arg = argv[i];
23647
+ if (arg.startsWith(`${flag}=`)) {
23648
+ return arg.slice(flag.length + 1);
23649
+ }
23650
+ if (arg === flag && i + 1 < argv.length) {
23651
+ return argv[i + 1];
23652
+ }
23653
+ }
23654
+ return void 0;
23655
+ }
23509
23656
  var subcommand = findSubcommand(process.argv);
23510
23657
  if (subcommand && commandsRequiringServer.includes(subcommand)) {
23511
- const apiKeyIdx = process.argv.indexOf("--api-key");
23512
- const endpointIdx = process.argv.indexOf("--endpoint");
23513
- const cliApiKey = apiKeyIdx !== -1 ? process.argv[apiKeyIdx + 1] : void 0;
23514
- const cliEndpoint = endpointIdx !== -1 ? process.argv[endpointIdx + 1] : void 0;
23658
+ const cliApiKey = extractFlagValue(process.argv, "--api-key");
23659
+ const cliEndpoint = extractFlagValue(process.argv, "--endpoint");
23515
23660
  const config = resolveConfig({ apiKey: cliApiKey, endpoint: cliEndpoint });
23516
23661
  if (config.apiKey) {
23517
23662
  checkVersionCompatibility(config.endpoint).then(() => program.parse());