@sulala/agent-os 0.1.24 → 0.1.26
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/dashboard-dist/assets/index-BZYG7rCd.js +75 -0
- package/dashboard-dist/assets/index-CAOgf_FY.css +1 -0
- package/dashboard-dist/index.html +2 -2
- package/data/skills/bluesky/SKILL.md +1 -1
- package/data/skills/content-writing/SKILL.md +1 -1
- package/data/skills/date/SKILL.md +1 -1
- package/data/skills/fetch/SKILL.md +1 -1
- package/data/skills/file-search/SKILL.md +1 -1
- package/data/skills/file-stats/SKILL.md +1 -1
- package/data/skills/git/SKILL.md +1 -1
- package/data/skills/hash/SKILL.md +1 -1
- package/data/skills/jq/SKILL.md +1 -1
- package/data/skills/markdown-to-html/SKILL.md +1 -1
- package/data/skills/qr-code/SKILL.md +1 -1
- package/data/skills/rss/SKILL.md +1 -1
- package/data/skills/translate/SKILL.md +1 -1
- package/data/skills/weather/SKILL.md +1 -1
- package/data/skills/web-search/SKILL.md +1 -1
- package/data/skills/webhook/SKILL.md +1 -1
- package/dist/cli.js +120 -25
- package/dist/index.js +55 -22
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -8451,6 +8451,28 @@ var init_skill_tools = () => {};
|
|
|
8451
8451
|
import { readFile as readFile5, readdir as readdir3, cp, mkdir as mkdir3, writeFile as writeFile3, rm } from "fs/promises";
|
|
8452
8452
|
import { join as join5, resolve as resolve2, basename } from "path";
|
|
8453
8453
|
import { tmpdir } from "os";
|
|
8454
|
+
async function readSkillMeta(skillDir, subEntries) {
|
|
8455
|
+
if (!subEntries.includes(SULALA_META_FILE))
|
|
8456
|
+
return null;
|
|
8457
|
+
try {
|
|
8458
|
+
const raw = await readFile5(join5(skillDir, SULALA_META_FILE), "utf-8");
|
|
8459
|
+
const data = JSON.parse(raw);
|
|
8460
|
+
return typeof data.version === "string" && data.version.trim() !== "" ? { version: data.version.trim() } : null;
|
|
8461
|
+
} catch {
|
|
8462
|
+
return null;
|
|
8463
|
+
}
|
|
8464
|
+
}
|
|
8465
|
+
async function writeSkillMeta(skillId, meta) {
|
|
8466
|
+
const skillDir = join5(getSkillsDir(), skillId);
|
|
8467
|
+
const payload = {};
|
|
8468
|
+
if (meta.version?.trim())
|
|
8469
|
+
payload.version = meta.version.trim();
|
|
8470
|
+
if (meta.source?.trim())
|
|
8471
|
+
payload.source = meta.source.trim();
|
|
8472
|
+
if (Object.keys(payload).length === 0)
|
|
8473
|
+
return;
|
|
8474
|
+
await writeFile3(join5(skillDir, SULALA_META_FILE), JSON.stringify(payload, null, 0), "utf-8");
|
|
8475
|
+
}
|
|
8454
8476
|
async function loadSkill(name) {
|
|
8455
8477
|
const dir = join5(getSkillsDir(), name);
|
|
8456
8478
|
let entries;
|
|
@@ -8693,10 +8715,14 @@ async function listSkills() {
|
|
|
8693
8715
|
continue;
|
|
8694
8716
|
const skillName = doc.name ?? name;
|
|
8695
8717
|
const requiredEnv = await getRequiredEnvForSkill(skillDir, subEntries, doc);
|
|
8718
|
+
const docVersion = doc.version?.trim() || undefined;
|
|
8719
|
+
const meta = await readSkillMeta(skillDir, subEntries);
|
|
8720
|
+
const version = docVersion ?? meta?.version;
|
|
8696
8721
|
results.push({
|
|
8697
8722
|
id: name,
|
|
8698
8723
|
name: skillName,
|
|
8699
8724
|
description: doc.description,
|
|
8725
|
+
version,
|
|
8700
8726
|
tools: (doc.tools ?? []).map((t) => ({ id: t.id, description: t.description })),
|
|
8701
8727
|
required_env: requiredEnv.length ? requiredEnv : undefined,
|
|
8702
8728
|
system: SYSTEM_SKILL_IDS.has(name)
|
|
@@ -8766,7 +8792,7 @@ async function installSystemSkills() {
|
|
|
8766
8792
|
}
|
|
8767
8793
|
return { installed };
|
|
8768
8794
|
}
|
|
8769
|
-
async function installSkillFromUrl(url, explicitId) {
|
|
8795
|
+
async function installSkillFromUrl(url, explicitId, meta) {
|
|
8770
8796
|
const urlLower = url.toLowerCase();
|
|
8771
8797
|
const isStoreSkillContentUrl = urlLower.includes("/api/sulalahub/skills/") && !urlLower.includes("/download") && !urlLower.endsWith(".zip");
|
|
8772
8798
|
const headers = isStoreSkillContentUrl ? { Accept: "application/zip" } : {};
|
|
@@ -8781,31 +8807,35 @@ async function installSkillFromUrl(url, explicitId) {
|
|
|
8781
8807
|
const tmpDir = join5(tmpdir(), `agent-os-skill-${Date.now()}`);
|
|
8782
8808
|
await mkdir3(tmpDir, { recursive: true });
|
|
8783
8809
|
try {
|
|
8810
|
+
let destId;
|
|
8784
8811
|
if (isZip) {
|
|
8785
8812
|
const zipPath = join5(tmpDir, "archive.zip");
|
|
8786
8813
|
await writeFile3(zipPath, new Uint8Array(buf));
|
|
8787
|
-
const
|
|
8788
|
-
const
|
|
8789
|
-
if (
|
|
8790
|
-
const err = await new Response(
|
|
8814
|
+
const proc = Bun.spawn({ cmd: ["unzip", "-q", "-o", zipPath, "-d", tmpDir], stdout: "ignore", stderr: "pipe" });
|
|
8815
|
+
const exit = await proc.exited;
|
|
8816
|
+
if (exit !== 0) {
|
|
8817
|
+
const err = await new Response(proc.stderr).text();
|
|
8791
8818
|
throw new Error(`unzip failed: ${err}`);
|
|
8792
8819
|
}
|
|
8793
|
-
const { id
|
|
8794
|
-
|
|
8795
|
-
await cp(
|
|
8796
|
-
|
|
8797
|
-
|
|
8798
|
-
|
|
8799
|
-
|
|
8800
|
-
|
|
8801
|
-
|
|
8802
|
-
|
|
8803
|
-
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
|
|
8808
|
-
|
|
8820
|
+
const { id, sourcePath } = await chooseSkillRootFromExtract(tmpDir, "archive.zip");
|
|
8821
|
+
destId = explicitId != null && explicitId.trim() !== "" ? slugToSkillId(explicitId) : id;
|
|
8822
|
+
await cp(sourcePath, join5(skillsDir, destId), { recursive: true });
|
|
8823
|
+
} else {
|
|
8824
|
+
const tarPath = join5(tmpDir, "archive.tar.gz");
|
|
8825
|
+
await writeFile3(tarPath, new Uint8Array(buf));
|
|
8826
|
+
const proc = Bun.spawn({ cmd: ["tar", "-xzf", tarPath, "-C", tmpDir], stdout: "ignore", stderr: "pipe" });
|
|
8827
|
+
const exit = await proc.exited;
|
|
8828
|
+
if (exit !== 0) {
|
|
8829
|
+
const err = await new Response(proc.stderr).text();
|
|
8830
|
+
throw new Error(`tar extract failed: ${err}`);
|
|
8831
|
+
}
|
|
8832
|
+
const { id, sourcePath } = await chooseSkillRootFromExtract(tmpDir, "archive.tar.gz");
|
|
8833
|
+
destId = explicitId != null && explicitId.trim() !== "" ? slugToSkillId(explicitId) : id;
|
|
8834
|
+
await cp(sourcePath, join5(skillsDir, destId), { recursive: true });
|
|
8835
|
+
}
|
|
8836
|
+
if (meta?.version?.trim() || meta?.source?.trim()) {
|
|
8837
|
+
await writeSkillMeta(destId, { version: meta.version, source: meta.source ?? (explicitId ? "hub" : undefined) });
|
|
8838
|
+
}
|
|
8809
8839
|
return { id: destId };
|
|
8810
8840
|
} finally {
|
|
8811
8841
|
await rm(tmpDir, { recursive: true, force: true });
|
|
@@ -8864,7 +8894,7 @@ async function installSkillFromSkillMd(buffer, filename, explicitId) {
|
|
|
8864
8894
|
await writeFile3(join5(destDir, "SKILL.md"), text, "utf-8");
|
|
8865
8895
|
return { id };
|
|
8866
8896
|
}
|
|
8867
|
-
var SYSTEM_SKILL_IDS, DEFAULT_SYSTEM_SKILL_IDS;
|
|
8897
|
+
var SYSTEM_SKILL_IDS, DEFAULT_SYSTEM_SKILL_IDS, SULALA_META_FILE = ".sulala-meta.json";
|
|
8868
8898
|
var init_loader = __esm(() => {
|
|
8869
8899
|
init_config();
|
|
8870
8900
|
init_tool_registry();
|
|
@@ -26095,8 +26125,10 @@ async function handleSkillInstall(req) {
|
|
|
26095
26125
|
return jsonResponse({ error: "Provide path or url" }, 400);
|
|
26096
26126
|
}
|
|
26097
26127
|
const slug = typeof body.slug === "string" && body.slug.trim() !== "" ? body.slug.trim() : undefined;
|
|
26128
|
+
const version2 = typeof body.version === "string" && body.version.trim() !== "" ? body.version.trim() : undefined;
|
|
26129
|
+
const meta = version2 || slug ? { version: version2, source: slug ? "hub" : undefined } : undefined;
|
|
26098
26130
|
try {
|
|
26099
|
-
const result = hasPath ? await installSkillFromPath(body.path.trim()) : await installSkillFromUrl(body.url.trim(), slug);
|
|
26131
|
+
const result = hasPath ? await installSkillFromPath(body.path.trim()) : await installSkillFromUrl(body.url.trim(), slug, meta);
|
|
26100
26132
|
return jsonResponse({ skill: result }, 201);
|
|
26101
26133
|
} catch (err) {
|
|
26102
26134
|
const msg = errorMessage(err);
|
|
@@ -30389,6 +30421,7 @@ Commands:
|
|
|
30389
30421
|
onboard First-time setup: create config, seed agents & skills, open dashboard
|
|
30390
30422
|
update Update package from npm and system agents/skills
|
|
30391
30423
|
run <agent_id> <task> Run an agent with a one-off task
|
|
30424
|
+
skill install <slug> Install a skill from the store by slug (e.g. crm-hubspot)
|
|
30392
30425
|
dashboard-token [--regenerate] Show or regenerate dashboard login token (copy to log in)
|
|
30393
30426
|
|
|
30394
30427
|
Examples:
|
|
@@ -30399,6 +30432,7 @@ Examples:
|
|
|
30399
30432
|
sulala onboard
|
|
30400
30433
|
sulala update
|
|
30401
30434
|
sulala run echo_agent What is 2+2?
|
|
30435
|
+
sulala skill install crm-hubspot
|
|
30402
30436
|
sulala dashboard-token
|
|
30403
30437
|
sulala dashboard-token --regenerate
|
|
30404
30438
|
`);
|
|
@@ -30520,14 +30554,21 @@ async function cmdOnboard() {
|
|
|
30520
30554
|
const started = await startServerDaemonIfNeeded();
|
|
30521
30555
|
if (started) {
|
|
30522
30556
|
console.log("Server starting in background. Use 'sulala stop' to stop.");
|
|
30523
|
-
await new Promise((r) => setTimeout(r, 1500));
|
|
30524
30557
|
}
|
|
30525
|
-
openDashboard();
|
|
30526
30558
|
const token = await getDashboardSecret();
|
|
30527
30559
|
console.log("");
|
|
30528
30560
|
console.log("Dashboard login token (copy and paste in the dashboard):");
|
|
30529
30561
|
console.log(token);
|
|
30530
30562
|
console.log("");
|
|
30563
|
+
const readline = await import("readline");
|
|
30564
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
30565
|
+
const answer = await new Promise((resolve5) => rl.question("Go to dashboard? (y/n): ", resolve5));
|
|
30566
|
+
rl.close();
|
|
30567
|
+
if (/^y(es)?$/i.test(answer.trim())) {
|
|
30568
|
+
if (started)
|
|
30569
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
30570
|
+
openDashboard();
|
|
30571
|
+
}
|
|
30531
30572
|
}
|
|
30532
30573
|
var NPM_PACKAGE = "@sulala/agent-os";
|
|
30533
30574
|
async function cmdUpdate() {
|
|
@@ -30605,6 +30646,57 @@ async function cmdRun(args) {
|
|
|
30605
30646
|
process.exit(1);
|
|
30606
30647
|
}
|
|
30607
30648
|
}
|
|
30649
|
+
async function cmdSkill(args) {
|
|
30650
|
+
const sub = args[0]?.toLowerCase();
|
|
30651
|
+
const rest = args.slice(1);
|
|
30652
|
+
if (sub === "install") {
|
|
30653
|
+
await cmdSkillInstall(rest);
|
|
30654
|
+
return;
|
|
30655
|
+
}
|
|
30656
|
+
if (!sub || sub === "help" || sub === "-h" || sub === "--help") {
|
|
30657
|
+
console.log("Usage: sulala skill install <slug>");
|
|
30658
|
+
console.log(" Install a skill from the store by slug (e.g. crm-hubspot).");
|
|
30659
|
+
console.log(" Installs the latest version; you can pin a specific version in your skill config if needed.");
|
|
30660
|
+
console.log("");
|
|
30661
|
+
console.log("Example: sulala skill install crm-hubspot");
|
|
30662
|
+
return;
|
|
30663
|
+
}
|
|
30664
|
+
console.error(`Unknown subcommand: skill ${sub}`);
|
|
30665
|
+
console.error("Usage: sulala skill install <slug>");
|
|
30666
|
+
process.exit(1);
|
|
30667
|
+
}
|
|
30668
|
+
async function cmdSkillInstall(args) {
|
|
30669
|
+
const slug = args[0]?.trim();
|
|
30670
|
+
if (!slug) {
|
|
30671
|
+
console.error("Usage: sulala skill install <slug>");
|
|
30672
|
+
console.error("Example: sulala skill install crm-hubspot");
|
|
30673
|
+
process.exit(1);
|
|
30674
|
+
}
|
|
30675
|
+
const { skills, storeBase } = await getStoreRegistry();
|
|
30676
|
+
if (!storeBase) {
|
|
30677
|
+
console.error("Could not reach the skills store. Check config (skills_registry_url) or run 'sulala onboard' first.");
|
|
30678
|
+
process.exit(1);
|
|
30679
|
+
}
|
|
30680
|
+
const entry = skills.find((s) => s.slug === slug);
|
|
30681
|
+
if (!entry) {
|
|
30682
|
+
console.error(`Skill '${slug}' not found in the store. Check the slug at hub.sulala.ai or install from the dashboard (Skills page).`);
|
|
30683
|
+
process.exit(1);
|
|
30684
|
+
}
|
|
30685
|
+
const downloadUrl = entry.downloadUrl ?? `${storeBase}/api/sulalahub/skills/${encodeURIComponent(slug)}/download`;
|
|
30686
|
+
const version2 = entry.version;
|
|
30687
|
+
try {
|
|
30688
|
+
const { id } = await installSkillFromUrl(downloadUrl, slug, {
|
|
30689
|
+
version: version2 ?? undefined,
|
|
30690
|
+
source: "hub"
|
|
30691
|
+
});
|
|
30692
|
+
const verStr = version2 ? ` (v${version2})` : "";
|
|
30693
|
+
console.log(`Installed ${id}${verStr}. Add it to your agent in the dashboard (Edit agent \u2192 Skills).`);
|
|
30694
|
+
} catch (err) {
|
|
30695
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
30696
|
+
console.error("Install failed:", msg);
|
|
30697
|
+
process.exit(1);
|
|
30698
|
+
}
|
|
30699
|
+
}
|
|
30608
30700
|
async function main() {
|
|
30609
30701
|
if (!process.versions.bun) {
|
|
30610
30702
|
console.error("Sulala CLI requires Bun. Use: bun run src/cli.ts");
|
|
@@ -30634,6 +30726,9 @@ async function main() {
|
|
|
30634
30726
|
case "run":
|
|
30635
30727
|
await cmdRun(rest);
|
|
30636
30728
|
break;
|
|
30729
|
+
case "skill":
|
|
30730
|
+
await cmdSkill(rest);
|
|
30731
|
+
break;
|
|
30637
30732
|
case "dashboard-token":
|
|
30638
30733
|
await cmdDashboardToken(rest);
|
|
30639
30734
|
break;
|
package/dist/index.js
CHANGED
|
@@ -19606,6 +19606,29 @@ function createTokenRequestTool(skillId, toolId, baseUrl, description) {
|
|
|
19606
19606
|
init_config();
|
|
19607
19607
|
var SYSTEM_SKILL_IDS = new Set(["memory"]);
|
|
19608
19608
|
var DEFAULT_SYSTEM_SKILL_IDS = ["memory", "date", "fetch", "jq", "file-search"];
|
|
19609
|
+
var SULALA_META_FILE = ".sulala-meta.json";
|
|
19610
|
+
async function readSkillMeta(skillDir, subEntries) {
|
|
19611
|
+
if (!subEntries.includes(SULALA_META_FILE))
|
|
19612
|
+
return null;
|
|
19613
|
+
try {
|
|
19614
|
+
const raw = await readFile5(join6(skillDir, SULALA_META_FILE), "utf-8");
|
|
19615
|
+
const data = JSON.parse(raw);
|
|
19616
|
+
return typeof data.version === "string" && data.version.trim() !== "" ? { version: data.version.trim() } : null;
|
|
19617
|
+
} catch {
|
|
19618
|
+
return null;
|
|
19619
|
+
}
|
|
19620
|
+
}
|
|
19621
|
+
async function writeSkillMeta(skillId, meta) {
|
|
19622
|
+
const skillDir = join6(getSkillsDir(), skillId);
|
|
19623
|
+
const payload = {};
|
|
19624
|
+
if (meta.version?.trim())
|
|
19625
|
+
payload.version = meta.version.trim();
|
|
19626
|
+
if (meta.source?.trim())
|
|
19627
|
+
payload.source = meta.source.trim();
|
|
19628
|
+
if (Object.keys(payload).length === 0)
|
|
19629
|
+
return;
|
|
19630
|
+
await writeFile3(join6(skillDir, SULALA_META_FILE), JSON.stringify(payload, null, 0), "utf-8");
|
|
19631
|
+
}
|
|
19609
19632
|
async function loadSkill(name) {
|
|
19610
19633
|
const dir = join6(getSkillsDir(), name);
|
|
19611
19634
|
let entries;
|
|
@@ -19848,10 +19871,14 @@ async function listSkills() {
|
|
|
19848
19871
|
continue;
|
|
19849
19872
|
const skillName = doc.name ?? name;
|
|
19850
19873
|
const requiredEnv = await getRequiredEnvForSkill(skillDir, subEntries, doc);
|
|
19874
|
+
const docVersion = doc.version?.trim() || undefined;
|
|
19875
|
+
const meta = await readSkillMeta(skillDir, subEntries);
|
|
19876
|
+
const version = docVersion ?? meta?.version;
|
|
19851
19877
|
results.push({
|
|
19852
19878
|
id: name,
|
|
19853
19879
|
name: skillName,
|
|
19854
19880
|
description: doc.description,
|
|
19881
|
+
version,
|
|
19855
19882
|
tools: (doc.tools ?? []).map((t) => ({ id: t.id, description: t.description })),
|
|
19856
19883
|
required_env: requiredEnv.length ? requiredEnv : undefined,
|
|
19857
19884
|
system: SYSTEM_SKILL_IDS.has(name)
|
|
@@ -19921,7 +19948,7 @@ async function installSystemSkills() {
|
|
|
19921
19948
|
}
|
|
19922
19949
|
return { installed };
|
|
19923
19950
|
}
|
|
19924
|
-
async function installSkillFromUrl(url, explicitId) {
|
|
19951
|
+
async function installSkillFromUrl(url, explicitId, meta) {
|
|
19925
19952
|
const urlLower = url.toLowerCase();
|
|
19926
19953
|
const isStoreSkillContentUrl = urlLower.includes("/api/sulalahub/skills/") && !urlLower.includes("/download") && !urlLower.endsWith(".zip");
|
|
19927
19954
|
const headers = isStoreSkillContentUrl ? { Accept: "application/zip" } : {};
|
|
@@ -19936,31 +19963,35 @@ async function installSkillFromUrl(url, explicitId) {
|
|
|
19936
19963
|
const tmpDir = join6(tmpdir(), `agent-os-skill-${Date.now()}`);
|
|
19937
19964
|
await mkdir3(tmpDir, { recursive: true });
|
|
19938
19965
|
try {
|
|
19966
|
+
let destId;
|
|
19939
19967
|
if (isZip) {
|
|
19940
19968
|
const zipPath = join6(tmpDir, "archive.zip");
|
|
19941
19969
|
await writeFile3(zipPath, new Uint8Array(buf));
|
|
19942
|
-
const
|
|
19943
|
-
const
|
|
19944
|
-
if (
|
|
19945
|
-
const err = await new Response(
|
|
19970
|
+
const proc = Bun.spawn({ cmd: ["unzip", "-q", "-o", zipPath, "-d", tmpDir], stdout: "ignore", stderr: "pipe" });
|
|
19971
|
+
const exit = await proc.exited;
|
|
19972
|
+
if (exit !== 0) {
|
|
19973
|
+
const err = await new Response(proc.stderr).text();
|
|
19946
19974
|
throw new Error(`unzip failed: ${err}`);
|
|
19947
19975
|
}
|
|
19948
|
-
const { id
|
|
19949
|
-
|
|
19950
|
-
await cp(
|
|
19951
|
-
|
|
19952
|
-
|
|
19953
|
-
|
|
19954
|
-
|
|
19955
|
-
|
|
19956
|
-
|
|
19957
|
-
|
|
19958
|
-
|
|
19959
|
-
|
|
19960
|
-
|
|
19961
|
-
|
|
19962
|
-
|
|
19963
|
-
|
|
19976
|
+
const { id, sourcePath } = await chooseSkillRootFromExtract(tmpDir, "archive.zip");
|
|
19977
|
+
destId = explicitId != null && explicitId.trim() !== "" ? slugToSkillId(explicitId) : id;
|
|
19978
|
+
await cp(sourcePath, join6(skillsDir, destId), { recursive: true });
|
|
19979
|
+
} else {
|
|
19980
|
+
const tarPath = join6(tmpDir, "archive.tar.gz");
|
|
19981
|
+
await writeFile3(tarPath, new Uint8Array(buf));
|
|
19982
|
+
const proc = Bun.spawn({ cmd: ["tar", "-xzf", tarPath, "-C", tmpDir], stdout: "ignore", stderr: "pipe" });
|
|
19983
|
+
const exit = await proc.exited;
|
|
19984
|
+
if (exit !== 0) {
|
|
19985
|
+
const err = await new Response(proc.stderr).text();
|
|
19986
|
+
throw new Error(`tar extract failed: ${err}`);
|
|
19987
|
+
}
|
|
19988
|
+
const { id, sourcePath } = await chooseSkillRootFromExtract(tmpDir, "archive.tar.gz");
|
|
19989
|
+
destId = explicitId != null && explicitId.trim() !== "" ? slugToSkillId(explicitId) : id;
|
|
19990
|
+
await cp(sourcePath, join6(skillsDir, destId), { recursive: true });
|
|
19991
|
+
}
|
|
19992
|
+
if (meta?.version?.trim() || meta?.source?.trim()) {
|
|
19993
|
+
await writeSkillMeta(destId, { version: meta.version, source: meta.source ?? (explicitId ? "hub" : undefined) });
|
|
19994
|
+
}
|
|
19964
19995
|
return { id: destId };
|
|
19965
19996
|
} finally {
|
|
19966
19997
|
await rm(tmpDir, { recursive: true, force: true });
|
|
@@ -27926,8 +27957,10 @@ async function handleSkillInstall(req) {
|
|
|
27926
27957
|
return jsonResponse({ error: "Provide path or url" }, 400);
|
|
27927
27958
|
}
|
|
27928
27959
|
const slug = typeof body.slug === "string" && body.slug.trim() !== "" ? body.slug.trim() : undefined;
|
|
27960
|
+
const version2 = typeof body.version === "string" && body.version.trim() !== "" ? body.version.trim() : undefined;
|
|
27961
|
+
const meta = version2 || slug ? { version: version2, source: slug ? "hub" : undefined } : undefined;
|
|
27929
27962
|
try {
|
|
27930
|
-
const result = hasPath ? await installSkillFromPath(body.path.trim()) : await installSkillFromUrl(body.url.trim(), slug);
|
|
27963
|
+
const result = hasPath ? await installSkillFromPath(body.path.trim()) : await installSkillFromUrl(body.url.trim(), slug, meta);
|
|
27931
27964
|
return jsonResponse({ skill: result }, 201);
|
|
27932
27965
|
} catch (err) {
|
|
27933
27966
|
const msg = errorMessage(err);
|