@superglue/cli 1.0.0 → 1.1.0
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/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# superglue CLI
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@superglue/cli)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
Build, test, and manage superglue API integration tools from the command line.
|
|
7
|
+
|
|
8
|
+
## What is superglue?
|
|
9
|
+
|
|
10
|
+
- AI-powered tool builder that works with any API, database or file storage server
|
|
11
|
+
- Abstracts away authentication, documentation handling and data mapping between systems
|
|
12
|
+
- Self-heals tools: when steps fail due to upstream API changes, superglue can auto-repair failures
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
### As npm package
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g @superglue/cli
|
|
20
|
+
sg --help
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### As Claude Code Plugin
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
/plugin install github:superglue-ai/cli
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
sg init # guided setup
|
|
33
|
+
sg system list # verify connection
|
|
34
|
+
sg tool build --config '...' # build a tool
|
|
35
|
+
sg tool run --draft <id> # test it
|
|
36
|
+
sg tool save --draft <id> # save it
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Commands
|
|
40
|
+
|
|
41
|
+
### Tools
|
|
42
|
+
|
|
43
|
+
- `sg tool build` — Build a tool from config
|
|
44
|
+
- `sg tool run` — Run a draft or saved tool
|
|
45
|
+
- `sg tool edit` — Edit via JSON Patch
|
|
46
|
+
- `sg tool save` — Save a draft
|
|
47
|
+
- `sg tool list` — List saved tools
|
|
48
|
+
- `sg tool find` — Search tools
|
|
49
|
+
|
|
50
|
+
### Systems
|
|
51
|
+
|
|
52
|
+
- `sg system create` — Create a system
|
|
53
|
+
- `sg system edit` — Edit system config
|
|
54
|
+
- `sg system list` — List systems
|
|
55
|
+
- `sg system find` — Search systems
|
|
56
|
+
- `sg system call` — Make authenticated API calls
|
|
57
|
+
- `sg system oauth` — Authenticate via OAuth
|
|
58
|
+
- `sg system docs` — Search system documentation
|
|
59
|
+
|
|
60
|
+
### Runs
|
|
61
|
+
|
|
62
|
+
- `sg run list` — List execution runs
|
|
63
|
+
- `sg run get` — Get run details
|
|
64
|
+
|
|
65
|
+
## Documentation
|
|
66
|
+
|
|
67
|
+
- [Full CLI Reference](./skills/superglue/SKILL.md) — Complete command documentation
|
|
68
|
+
- [superglue Docs](https://docs.superglue.cloud) — Platform documentation
|
|
69
|
+
- [API Reference](https://docs.superglue.cloud/api-reference/) — REST API docs
|
|
70
|
+
|
|
71
|
+
## Related
|
|
72
|
+
|
|
73
|
+
- [superglue Web App](https://app.superglue.cloud) — Visual tool builder
|
|
74
|
+
- [@superglue/client](https://www.npmjs.com/package/@superglue/client) — TypeScript SDK
|
|
75
|
+
- [superglue-client](https://pypi.org/project/superglue-client/) — Python SDK
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT
|
package/dist/cli.js
CHANGED
|
@@ -21645,7 +21645,9 @@ function resolveConfig(flags) {
|
|
|
21645
21645
|
function writeConfig(config, preferLocal) {
|
|
21646
21646
|
const dir = getConfigDir(preferLocal);
|
|
21647
21647
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
21648
|
-
fs.writeFileSync(path.join(dir, "config.json"), JSON.stringify(config, null, 2) + "\n"
|
|
21648
|
+
fs.writeFileSync(path.join(dir, "config.json"), JSON.stringify(config, null, 2) + "\n", {
|
|
21649
|
+
mode: 384
|
|
21650
|
+
});
|
|
21649
21651
|
}
|
|
21650
21652
|
function ensureConfigDirs(config, preferLocal) {
|
|
21651
21653
|
const draftsDir = path.join(getConfigDir(preferLocal), "drafts");
|
|
@@ -21677,6 +21679,125 @@ var import_shared2 = __toESM(require_dist2());
|
|
|
21677
21679
|
|
|
21678
21680
|
// src/output.ts
|
|
21679
21681
|
var readline = __toESM(require("readline"));
|
|
21682
|
+
|
|
21683
|
+
// src/version.ts
|
|
21684
|
+
var import_node_child_process = require("child_process");
|
|
21685
|
+
var import_node_util = require("util");
|
|
21686
|
+
|
|
21687
|
+
// package.json
|
|
21688
|
+
var package_default = {
|
|
21689
|
+
name: "@superglue/cli",
|
|
21690
|
+
version: "1.1.0",
|
|
21691
|
+
bin: {
|
|
21692
|
+
sg: "./dist/cli.js"
|
|
21693
|
+
},
|
|
21694
|
+
files: [
|
|
21695
|
+
"dist/",
|
|
21696
|
+
"skills/",
|
|
21697
|
+
"skills.md"
|
|
21698
|
+
],
|
|
21699
|
+
dependencies: {
|
|
21700
|
+
commander: "^13.0.0",
|
|
21701
|
+
"fast-json-patch": "^3.1.1"
|
|
21702
|
+
},
|
|
21703
|
+
devDependencies: {
|
|
21704
|
+
"@superglue/shared": "file:../shared",
|
|
21705
|
+
"@types/node": "^20.0.0",
|
|
21706
|
+
tsup: "^8.0.0",
|
|
21707
|
+
typescript: "^5.0.0"
|
|
21708
|
+
},
|
|
21709
|
+
scripts: {
|
|
21710
|
+
build: "tsup && (cp -r skills dist/ 2>/dev/null || true)",
|
|
21711
|
+
dev: "tsup --watch",
|
|
21712
|
+
"type-check": "tsc --noEmit",
|
|
21713
|
+
prepublishOnly: "npm run build"
|
|
21714
|
+
},
|
|
21715
|
+
publishConfig: {
|
|
21716
|
+
access: "public"
|
|
21717
|
+
}
|
|
21718
|
+
};
|
|
21719
|
+
|
|
21720
|
+
// src/version.ts
|
|
21721
|
+
var execAsync = (0, import_node_util.promisify)(import_node_child_process.exec);
|
|
21722
|
+
var CLI_VERSION = package_default.version;
|
|
21723
|
+
function parseVersionPart(part) {
|
|
21724
|
+
const match = part.match(/^(\d+)(?:-(.+))?$/);
|
|
21725
|
+
if (match) {
|
|
21726
|
+
return { numeric: parseInt(match[1], 10), prerelease: match[2] || null };
|
|
21727
|
+
}
|
|
21728
|
+
return { numeric: 0, prerelease: part };
|
|
21729
|
+
}
|
|
21730
|
+
function compareVersions(a, b) {
|
|
21731
|
+
const partsA = a.split(".");
|
|
21732
|
+
const partsB = b.split(".");
|
|
21733
|
+
const maxLen = Math.max(partsA.length, partsB.length);
|
|
21734
|
+
for (let i = 0; i < maxLen; i++) {
|
|
21735
|
+
const parsedA = parseVersionPart(partsA[i] || "0");
|
|
21736
|
+
const parsedB = parseVersionPart(partsB[i] || "0");
|
|
21737
|
+
if (parsedA.numeric < parsedB.numeric) return -1;
|
|
21738
|
+
if (parsedA.numeric > parsedB.numeric) return 1;
|
|
21739
|
+
if (parsedA.prerelease === null && parsedB.prerelease !== null) return 1;
|
|
21740
|
+
if (parsedA.prerelease !== null && parsedB.prerelease === null) return -1;
|
|
21741
|
+
if (parsedA.prerelease !== null && parsedB.prerelease !== null) {
|
|
21742
|
+
if (parsedA.prerelease < parsedB.prerelease) return -1;
|
|
21743
|
+
if (parsedA.prerelease > parsedB.prerelease) return 1;
|
|
21744
|
+
}
|
|
21745
|
+
}
|
|
21746
|
+
return 0;
|
|
21747
|
+
}
|
|
21748
|
+
async function checkVersionCompatibility(endpoint) {
|
|
21749
|
+
try {
|
|
21750
|
+
const healthUrl = `${endpoint.replace(/\/$/, "")}/v1/health`;
|
|
21751
|
+
const response = await fetch(healthUrl, { signal: AbortSignal.timeout(3e3) });
|
|
21752
|
+
if (!response.ok) return;
|
|
21753
|
+
const health = await response.json();
|
|
21754
|
+
if (!health.minCliVersion) return;
|
|
21755
|
+
if (compareVersions(CLI_VERSION, health.minCliVersion) < 0) {
|
|
21756
|
+
console.error("");
|
|
21757
|
+
console.error(`${c.yellow}${c.bold}\u26A0 CLI version ${CLI_VERSION} is outdated.${c.reset}`);
|
|
21758
|
+
console.error(
|
|
21759
|
+
`${c.yellow} Server requires at least v${health.minCliVersion}. Run: ${c.bold}sg update${c.reset}`
|
|
21760
|
+
);
|
|
21761
|
+
console.error("");
|
|
21762
|
+
}
|
|
21763
|
+
} catch {
|
|
21764
|
+
}
|
|
21765
|
+
}
|
|
21766
|
+
async function getLatestNpmVersion() {
|
|
21767
|
+
try {
|
|
21768
|
+
const response = await fetch("https://registry.npmjs.org/@superglue/cli/latest", {
|
|
21769
|
+
signal: AbortSignal.timeout(5e3)
|
|
21770
|
+
});
|
|
21771
|
+
if (!response.ok) return null;
|
|
21772
|
+
const data = await response.json();
|
|
21773
|
+
return data.version || null;
|
|
21774
|
+
} catch {
|
|
21775
|
+
return null;
|
|
21776
|
+
}
|
|
21777
|
+
}
|
|
21778
|
+
async function updateCli() {
|
|
21779
|
+
const latestVersion = await getLatestNpmVersion();
|
|
21780
|
+
if (!latestVersion) {
|
|
21781
|
+
return { success: false, message: "Could not fetch latest version from npm" };
|
|
21782
|
+
}
|
|
21783
|
+
if (compareVersions(CLI_VERSION, latestVersion) >= 0) {
|
|
21784
|
+
return { success: true, message: `Already on latest version (${CLI_VERSION})` };
|
|
21785
|
+
}
|
|
21786
|
+
try {
|
|
21787
|
+
await execAsync("npm install -g @superglue/cli@latest");
|
|
21788
|
+
return {
|
|
21789
|
+
success: true,
|
|
21790
|
+
message: `Updated from ${CLI_VERSION} to ${latestVersion}`
|
|
21791
|
+
};
|
|
21792
|
+
} catch (err) {
|
|
21793
|
+
return {
|
|
21794
|
+
success: false,
|
|
21795
|
+
message: `Update failed: ${err.message}. Try manually: npm install -g @superglue/cli@latest`
|
|
21796
|
+
};
|
|
21797
|
+
}
|
|
21798
|
+
}
|
|
21799
|
+
|
|
21800
|
+
// src/output.ts
|
|
21680
21801
|
var isJsonMode = () => process.argv.includes("--json") || !process.stdout.isTTY;
|
|
21681
21802
|
var c = {
|
|
21682
21803
|
reset: "\x1B[0m",
|
|
@@ -21729,7 +21850,7 @@ function banner() {
|
|
|
21729
21850
|
const after = line.slice(last + 1);
|
|
21730
21851
|
console.log(` ${before}${inv}${inside}${rst}${after}`);
|
|
21731
21852
|
});
|
|
21732
|
-
console.log(` ${d} CLI
|
|
21853
|
+
console.log(` ${d} CLI v${CLI_VERSION}${rst}`);
|
|
21733
21854
|
console.log("");
|
|
21734
21855
|
}
|
|
21735
21856
|
function spinner(message) {
|
|
@@ -21782,6 +21903,11 @@ function error(message, details) {
|
|
|
21782
21903
|
if (details) prettyPrint(details, 4);
|
|
21783
21904
|
}
|
|
21784
21905
|
}
|
|
21906
|
+
function warn(message) {
|
|
21907
|
+
if (!isJsonMode()) {
|
|
21908
|
+
console.log(` ${c.yellow}\u26A0${c.reset} ${message}`);
|
|
21909
|
+
}
|
|
21910
|
+
}
|
|
21785
21911
|
function info(message) {
|
|
21786
21912
|
if (!isJsonMode()) {
|
|
21787
21913
|
console.log(` ${c.dim}${message}${c.reset}`);
|
|
@@ -21974,22 +22100,25 @@ async function promptHidden(message) {
|
|
|
21974
22100
|
let input = "";
|
|
21975
22101
|
const onData = (ch) => {
|
|
21976
22102
|
const s = ch.toString();
|
|
21977
|
-
|
|
21978
|
-
if (
|
|
21979
|
-
|
|
21980
|
-
|
|
21981
|
-
|
|
21982
|
-
|
|
21983
|
-
|
|
21984
|
-
|
|
21985
|
-
|
|
21986
|
-
|
|
21987
|
-
|
|
21988
|
-
|
|
22103
|
+
for (const char of s) {
|
|
22104
|
+
if (char === "\n" || char === "\r") {
|
|
22105
|
+
if (process.stdin.isTTY) process.stdin.setRawMode(false);
|
|
22106
|
+
process.stdin.removeListener("data", onData);
|
|
22107
|
+
process.stdout.write("\n");
|
|
22108
|
+
rl.close();
|
|
22109
|
+
resolve4(input);
|
|
22110
|
+
return;
|
|
22111
|
+
} else if (char === "") {
|
|
22112
|
+
process.exit(130);
|
|
22113
|
+
} else if (char === "\x7F" || char === "\b") {
|
|
22114
|
+
if (input.length > 0) {
|
|
22115
|
+
input = input.slice(0, -1);
|
|
22116
|
+
process.stdout.write("\b \b");
|
|
22117
|
+
}
|
|
22118
|
+
} else {
|
|
22119
|
+
input += char;
|
|
22120
|
+
process.stdout.write(`${c.dim}\u2022${c.reset}`);
|
|
21989
22121
|
}
|
|
21990
|
-
} else {
|
|
21991
|
-
input += s;
|
|
21992
|
-
process.stdout.write(`${c.dim}\u2022${c.reset}`);
|
|
21993
22122
|
}
|
|
21994
22123
|
};
|
|
21995
22124
|
process.stdin.on("data", onData);
|
|
@@ -22151,9 +22280,11 @@ var path3 = __toESM(require("path"));
|
|
|
22151
22280
|
function getDraftsDir() {
|
|
22152
22281
|
return path3.join(getConfigDir(), "drafts");
|
|
22153
22282
|
}
|
|
22283
|
+
function encodeDraftId(draftId) {
|
|
22284
|
+
return Buffer.from(draftId, "utf-8").toString("base64url");
|
|
22285
|
+
}
|
|
22154
22286
|
function getDraftPath(draftId) {
|
|
22155
|
-
|
|
22156
|
-
return path3.join(getDraftsDir(), `${safeName}.json`);
|
|
22287
|
+
return path3.join(getDraftsDir(), `${encodeDraftId(draftId)}.json`);
|
|
22157
22288
|
}
|
|
22158
22289
|
function writeDraft(draft) {
|
|
22159
22290
|
const dir = getDraftsDir();
|
|
@@ -22471,11 +22602,11 @@ function registerEditCommand(parent, getContext2) {
|
|
|
22471
22602
|
draftId: workingDraftId,
|
|
22472
22603
|
config: {
|
|
22473
22604
|
...patchedConfig,
|
|
22474
|
-
instruction:
|
|
22605
|
+
instruction: patchedConfig.instruction ?? originalConfig.instruction,
|
|
22475
22606
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
22476
22607
|
},
|
|
22477
22608
|
systemIds: patchedConfig.systemIds || [],
|
|
22478
|
-
instruction: patchedConfig.instruction
|
|
22609
|
+
instruction: patchedConfig.instruction ?? "",
|
|
22479
22610
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
22480
22611
|
};
|
|
22481
22612
|
writeDraft(draft);
|
|
@@ -22541,8 +22672,8 @@ function registerSaveCommand(parent, getContext2) {
|
|
|
22541
22672
|
process.exit(1);
|
|
22542
22673
|
}
|
|
22543
22674
|
const toolId = opts.id || draft.config.id;
|
|
22675
|
+
const spin = spinner(`Saving tool ${c.bold}${toolId}${c.reset}...`);
|
|
22544
22676
|
try {
|
|
22545
|
-
const spin = spinner(`Saving tool ${c.bold}${toolId}${c.reset}...`);
|
|
22546
22677
|
const saved = await client.upsertWorkflow(toolId, {
|
|
22547
22678
|
...draft.config,
|
|
22548
22679
|
id: toolId,
|
|
@@ -22564,6 +22695,7 @@ function registerSaveCommand(parent, getContext2) {
|
|
|
22564
22695
|
console.log("");
|
|
22565
22696
|
}
|
|
22566
22697
|
} catch (err) {
|
|
22698
|
+
spin.stop();
|
|
22567
22699
|
error(err.message);
|
|
22568
22700
|
process.exit(1);
|
|
22569
22701
|
}
|
|
@@ -22602,7 +22734,7 @@ function registerFindCommand(parent, getContext2) {
|
|
|
22602
22734
|
output({ success: true, tool });
|
|
22603
22735
|
return;
|
|
22604
22736
|
}
|
|
22605
|
-
const searchQuery = query || "*";
|
|
22737
|
+
const searchQuery = (query || "").trim() || "*";
|
|
22606
22738
|
if (searchQuery === "*") {
|
|
22607
22739
|
const { items } = await client.listWorkflows(100);
|
|
22608
22740
|
const tools = items.filter((t) => !t.archived).map((t) => ({
|
|
@@ -22703,10 +22835,10 @@ function registerCreateCommand(parent, getContext2) {
|
|
|
22703
22835
|
if (template.oauth.client_id) oauthCreds.client_id = template.oauth.client_id;
|
|
22704
22836
|
}
|
|
22705
22837
|
systemInput = {
|
|
22838
|
+
...systemInput,
|
|
22706
22839
|
name: systemInput.name || template.name,
|
|
22707
|
-
url: template.apiUrl,
|
|
22840
|
+
url: systemInput.url || template.apiUrl,
|
|
22708
22841
|
templateName: opts.template,
|
|
22709
|
-
...systemInput,
|
|
22710
22842
|
credentials: { ...oauthCreds, ...systemInput.credentials }
|
|
22711
22843
|
};
|
|
22712
22844
|
}
|
|
@@ -22805,7 +22937,9 @@ function registerEditCommand2(parent, getContext2) {
|
|
|
22805
22937
|
url: opts.scrapeUrl,
|
|
22806
22938
|
keywords
|
|
22807
22939
|
});
|
|
22808
|
-
} catch {
|
|
22940
|
+
} catch (scrapeErr) {
|
|
22941
|
+
const errMsg = scrapeErr instanceof Error ? scrapeErr.message : String(scrapeErr || "Unknown error");
|
|
22942
|
+
warn(`Documentation scrape failed for ${opts.scrapeUrl}: ${errMsg}`);
|
|
22809
22943
|
}
|
|
22810
22944
|
}
|
|
22811
22945
|
spin.stop();
|
|
@@ -22921,14 +23055,29 @@ function registerCallCommand(parent, getContext2) {
|
|
|
22921
23055
|
if (body && Object.keys(filePayloads).length > 0) {
|
|
22922
23056
|
try {
|
|
22923
23057
|
let parsed = JSON.parse(body);
|
|
22924
|
-
|
|
22925
|
-
if (typeof
|
|
22926
|
-
const key =
|
|
22927
|
-
if (key in filePayloads)
|
|
23058
|
+
const resolveFileRefs = (obj) => {
|
|
23059
|
+
if (typeof obj === "string" && obj.startsWith("file::")) {
|
|
23060
|
+
const key = obj.slice(6);
|
|
23061
|
+
if (key in filePayloads) return filePayloads[key];
|
|
23062
|
+
error(
|
|
23063
|
+
`Unresolved file reference: file::${key}. Available: ${Object.keys(filePayloads).join(", ") || "(none)"}`
|
|
23064
|
+
);
|
|
23065
|
+
process.exit(1);
|
|
22928
23066
|
}
|
|
22929
|
-
|
|
23067
|
+
if (Array.isArray(obj)) return obj.map(resolveFileRefs);
|
|
23068
|
+
if (obj && typeof obj === "object") {
|
|
23069
|
+
const result = {};
|
|
23070
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
23071
|
+
result[k] = resolveFileRefs(v);
|
|
23072
|
+
}
|
|
23073
|
+
return result;
|
|
23074
|
+
}
|
|
23075
|
+
return obj;
|
|
23076
|
+
};
|
|
23077
|
+
parsed = resolveFileRefs(parsed);
|
|
22930
23078
|
body = JSON.stringify(parsed);
|
|
22931
|
-
} catch {
|
|
23079
|
+
} catch (err) {
|
|
23080
|
+
if (err.message?.startsWith("Unresolved file reference")) throw err;
|
|
22932
23081
|
}
|
|
22933
23082
|
}
|
|
22934
23083
|
const autoExec = process.argv.includes("--yes") || process.argv.includes("-y") || shouldAutoExecute(config.policies.callSystem, method, opts.url);
|
|
@@ -23041,13 +23190,13 @@ function registerDocsCommand(parent, getContext2) {
|
|
|
23041
23190
|
}
|
|
23042
23191
|
|
|
23043
23192
|
// src/commands/system/oauth.ts
|
|
23044
|
-
var
|
|
23193
|
+
var import_node_child_process2 = require("child_process");
|
|
23045
23194
|
var import_shared8 = __toESM(require_dist2());
|
|
23046
23195
|
function openBrowser(url) {
|
|
23047
23196
|
const platform = process.platform;
|
|
23048
23197
|
const cmd = platform === "darwin" ? "open" : platform === "win32" ? "cmd" : "xdg-open";
|
|
23049
23198
|
const args = platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
23050
|
-
(0,
|
|
23199
|
+
(0, import_node_child_process2.spawn)(cmd, args, { detached: true, stdio: "ignore" }).unref();
|
|
23051
23200
|
}
|
|
23052
23201
|
async function pollForTokens(client, systemId, originalToken, timeoutMs = 3e5, intervalMs = 2e3) {
|
|
23053
23202
|
const start = Date.now();
|
|
@@ -23207,12 +23356,12 @@ function registerSystemCommands(program2, getContext2) {
|
|
|
23207
23356
|
|
|
23208
23357
|
// src/commands/run/list.ts
|
|
23209
23358
|
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").
|
|
23359
|
+
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
23360
|
const { client } = getContext2();
|
|
23212
23361
|
try {
|
|
23213
23362
|
const limit = Math.min(parseInt(opts.limit, 10) || 10, 50);
|
|
23214
23363
|
const offset = parseInt(opts.offset, 10) || 0;
|
|
23215
|
-
const page = Math.
|
|
23364
|
+
const page = Math.ceil((offset + 1) / limit);
|
|
23216
23365
|
const requestSources = opts.source?.split(",").filter(Boolean);
|
|
23217
23366
|
const result = await client.listRuns({
|
|
23218
23367
|
toolId: opts.tool,
|
|
@@ -23295,109 +23444,6 @@ function registerRunCommands(program2, getContext2) {
|
|
|
23295
23444
|
registerGetCommand(run, getContext2);
|
|
23296
23445
|
}
|
|
23297
23446
|
|
|
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
23447
|
// src/commands/update.ts
|
|
23402
23448
|
function registerUpdateCommand(program2) {
|
|
23403
23449
|
program2.command("update").description("Update the superglue CLI to the latest version").option("--check", "Only check for updates, don't install").action(async (opts) => {
|
|
@@ -23506,12 +23552,22 @@ function findSubcommand(argv) {
|
|
|
23506
23552
|
}
|
|
23507
23553
|
return void 0;
|
|
23508
23554
|
}
|
|
23555
|
+
function extractFlagValue(argv, flag) {
|
|
23556
|
+
for (let i = 0; i < argv.length; i++) {
|
|
23557
|
+
const arg = argv[i];
|
|
23558
|
+
if (arg.startsWith(`${flag}=`)) {
|
|
23559
|
+
return arg.slice(flag.length + 1);
|
|
23560
|
+
}
|
|
23561
|
+
if (arg === flag && i + 1 < argv.length) {
|
|
23562
|
+
return argv[i + 1];
|
|
23563
|
+
}
|
|
23564
|
+
}
|
|
23565
|
+
return void 0;
|
|
23566
|
+
}
|
|
23509
23567
|
var subcommand = findSubcommand(process.argv);
|
|
23510
23568
|
if (subcommand && commandsRequiringServer.includes(subcommand)) {
|
|
23511
|
-
const
|
|
23512
|
-
const
|
|
23513
|
-
const cliApiKey = apiKeyIdx !== -1 ? process.argv[apiKeyIdx + 1] : void 0;
|
|
23514
|
-
const cliEndpoint = endpointIdx !== -1 ? process.argv[endpointIdx + 1] : void 0;
|
|
23569
|
+
const cliApiKey = extractFlagValue(process.argv, "--api-key");
|
|
23570
|
+
const cliEndpoint = extractFlagValue(process.argv, "--endpoint");
|
|
23515
23571
|
const config = resolveConfig({ apiKey: cliApiKey, endpoint: cliEndpoint });
|
|
23516
23572
|
if (config.apiKey) {
|
|
23517
23573
|
checkVersionCompatibility(config.endpoint).then(() => program.parse());
|
|
@@ -227,14 +227,14 @@ sg system oauth --system-id my_api --grant-type client_credentials --scopes "rea
|
|
|
227
227
|
{
|
|
228
228
|
"id": "unique-step-id",
|
|
229
229
|
"config": {
|
|
230
|
-
"systemId": "
|
|
231
|
-
"url": "https://api.example.com/endpoint?param=<<
|
|
230
|
+
"systemId": "example_system",
|
|
231
|
+
"url": "https://api.example.com/endpoint?param=<<payload_field>>",
|
|
232
232
|
"method": "GET",
|
|
233
233
|
"headers": {
|
|
234
|
-
"Authorization": "Bearer <<
|
|
234
|
+
"Authorization": "Bearer <<example_system_access_token>>"
|
|
235
235
|
},
|
|
236
236
|
"queryParams": { "limit": "10" },
|
|
237
|
-
"body": "{ \"key\": \"<<
|
|
237
|
+
"body": "{ \"key\": \"<<payload_field>>\" }"
|
|
238
238
|
},
|
|
239
239
|
"dataSelector": "(sourceData) => sourceData.previousStep.data.items",
|
|
240
240
|
"transformCode": "(items) => items.map(i => ({ id: i.id, name: i.name }))",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superglue/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"bin": {
|
|
5
5
|
"sg": "./dist/cli.js"
|
|
6
6
|
},
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"typescript": "^5.0.0"
|
|
21
21
|
},
|
|
22
22
|
"scripts": {
|
|
23
|
-
"build": "tsup && cp -r skills dist/ 2>/dev/null || true",
|
|
23
|
+
"build": "tsup && (cp -r skills dist/ 2>/dev/null || true)",
|
|
24
24
|
"dev": "tsup --watch",
|
|
25
25
|
"type-check": "tsc --noEmit",
|
|
26
26
|
"prepublishOnly": "npm run build"
|
|
@@ -227,14 +227,14 @@ sg system oauth --system-id my_api --grant-type client_credentials --scopes "rea
|
|
|
227
227
|
{
|
|
228
228
|
"id": "unique-step-id",
|
|
229
229
|
"config": {
|
|
230
|
-
"systemId": "
|
|
231
|
-
"url": "https://api.example.com/endpoint?param=<<
|
|
230
|
+
"systemId": "example_system",
|
|
231
|
+
"url": "https://api.example.com/endpoint?param=<<payload_field>>",
|
|
232
232
|
"method": "GET",
|
|
233
233
|
"headers": {
|
|
234
|
-
"Authorization": "Bearer <<
|
|
234
|
+
"Authorization": "Bearer <<example_system_access_token>>"
|
|
235
235
|
},
|
|
236
236
|
"queryParams": { "limit": "10" },
|
|
237
|
-
"body": "{ \"key\": \"<<
|
|
237
|
+
"body": "{ \"key\": \"<<payload_field>>\" }"
|
|
238
238
|
},
|
|
239
239
|
"dataSelector": "(sourceData) => sourceData.previousStep.data.items",
|
|
240
240
|
"transformCode": "(items) => items.map(i => ({ id: i.id, name: i.name }))",
|