nextclaw 0.9.11 → 0.9.12
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/index.js +130 -16
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
resolvePluginChannelMessageToolHints as resolvePluginChannelMessageToolHints2,
|
|
27
27
|
setPluginRuntimeBridge as setPluginRuntimeBridge2
|
|
28
28
|
} from "@nextclaw/openclaw-compat";
|
|
29
|
-
import { existsSync as existsSync10, mkdirSync as mkdirSync6, readFileSync as readFileSync8, writeFileSync as
|
|
29
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
|
|
30
30
|
import { join as join7, resolve as resolve9 } from "path";
|
|
31
31
|
import { createInterface as createInterface2 } from "readline";
|
|
32
32
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
@@ -2252,7 +2252,7 @@ import {
|
|
|
2252
2252
|
stopPluginChannelGateways
|
|
2253
2253
|
} from "@nextclaw/openclaw-compat";
|
|
2254
2254
|
import { startUiServer } from "@nextclaw/server";
|
|
2255
|
-
import { appendFileSync, closeSync, cpSync, existsSync as existsSync8, mkdirSync as mkdirSync4, mkdtempSync, openSync, rmSync as rmSync3 } from "fs";
|
|
2255
|
+
import { appendFileSync, closeSync, cpSync, existsSync as existsSync8, mkdirSync as mkdirSync4, mkdtempSync, openSync, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
2256
2256
|
import { dirname, isAbsolute as isAbsolute2, join as join5, relative, resolve as resolve7 } from "path";
|
|
2257
2257
|
import { tmpdir } from "os";
|
|
2258
2258
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -4391,33 +4391,51 @@ var ServiceCommands = class {
|
|
|
4391
4391
|
}
|
|
4392
4392
|
async materializeMarketplaceGitSkillSource(params) {
|
|
4393
4393
|
const parsed = this.parseMarketplaceGitSkillSource(params.source);
|
|
4394
|
-
const gitPath =
|
|
4395
|
-
|
|
4396
|
-
|
|
4394
|
+
const gitPath = this.resolveGitExecutablePath();
|
|
4395
|
+
const fallbackNotes = [];
|
|
4396
|
+
if (gitPath) {
|
|
4397
|
+
try {
|
|
4398
|
+
return await this.materializeMarketplaceGitSkillViaGit({ gitPath, parsed });
|
|
4399
|
+
} catch (error) {
|
|
4400
|
+
fallbackNotes.push(`Git fast path failed: ${String(error)}`);
|
|
4401
|
+
}
|
|
4402
|
+
} else {
|
|
4403
|
+
fallbackNotes.push("Git fast path unavailable: git executable not found");
|
|
4397
4404
|
}
|
|
4405
|
+
const httpResult = await this.materializeMarketplaceGitSkillViaGithubApi(parsed);
|
|
4406
|
+
return {
|
|
4407
|
+
...httpResult,
|
|
4408
|
+
commandOutput: [...fallbackNotes, httpResult.commandOutput].filter(Boolean).join("\n")
|
|
4409
|
+
};
|
|
4410
|
+
}
|
|
4411
|
+
resolveGitExecutablePath() {
|
|
4412
|
+
return findExecutableOnPath("git");
|
|
4413
|
+
}
|
|
4414
|
+
async materializeMarketplaceGitSkillViaGit(params) {
|
|
4398
4415
|
const tempRoot = mkdtempSync(join5(tmpdir(), "nextclaw-marketplace-skill-"));
|
|
4399
4416
|
const repoDir = join5(tempRoot, "repo");
|
|
4400
4417
|
try {
|
|
4401
4418
|
const cloneArgs = ["clone", "--depth", "1", "--filter=blob:none", "--sparse"];
|
|
4402
|
-
if (parsed.ref) {
|
|
4403
|
-
cloneArgs.push("--branch", parsed.ref);
|
|
4419
|
+
if (params.parsed.ref) {
|
|
4420
|
+
cloneArgs.push("--branch", params.parsed.ref);
|
|
4404
4421
|
}
|
|
4405
|
-
cloneArgs.push(parsed.repoUrl, repoDir);
|
|
4406
|
-
const cloneResult = await this.runCommand(gitPath, cloneArgs, {
|
|
4422
|
+
cloneArgs.push(params.parsed.repoUrl, repoDir);
|
|
4423
|
+
const cloneResult = await this.runCommand(params.gitPath, cloneArgs, {
|
|
4407
4424
|
cwd: tempRoot,
|
|
4408
4425
|
timeoutMs: 18e4
|
|
4409
4426
|
});
|
|
4410
|
-
const sparseResult = await this.runCommand(gitPath, ["-C", repoDir, "sparse-checkout", "set", parsed.skillPath], {
|
|
4427
|
+
const sparseResult = await this.runCommand(params.gitPath, ["-C", repoDir, "sparse-checkout", "set", params.parsed.skillPath], {
|
|
4411
4428
|
cwd: tempRoot,
|
|
4412
4429
|
timeoutMs: 6e4
|
|
4413
4430
|
});
|
|
4414
|
-
const skillDir = join5(repoDir, parsed.skillPath);
|
|
4431
|
+
const skillDir = join5(repoDir, params.parsed.skillPath);
|
|
4415
4432
|
return {
|
|
4416
4433
|
tempRoot,
|
|
4417
4434
|
skillDir,
|
|
4418
4435
|
commandOutput: [
|
|
4419
|
-
|
|
4420
|
-
`Git
|
|
4436
|
+
"Installer path: git-sparse",
|
|
4437
|
+
`Git repository: ${params.parsed.repoUrl}`,
|
|
4438
|
+
`Git path: ${params.parsed.skillPath}`,
|
|
4421
4439
|
this.mergeCommandOutput(cloneResult.stdout, cloneResult.stderr),
|
|
4422
4440
|
this.mergeCommandOutput(sparseResult.stdout, sparseResult.stderr)
|
|
4423
4441
|
].filter(Boolean).join("\n")
|
|
@@ -4427,6 +4445,98 @@ var ServiceCommands = class {
|
|
|
4427
4445
|
throw error;
|
|
4428
4446
|
}
|
|
4429
4447
|
}
|
|
4448
|
+
async materializeMarketplaceGitSkillViaGithubApi(parsed) {
|
|
4449
|
+
const tempRoot = mkdtempSync(join5(tmpdir(), "nextclaw-marketplace-skill-"));
|
|
4450
|
+
const skillDir = join5(tempRoot, "skill");
|
|
4451
|
+
const downloadedFiles = [];
|
|
4452
|
+
try {
|
|
4453
|
+
mkdirSync4(skillDir, { recursive: true });
|
|
4454
|
+
await this.downloadGithubDirectoryToPath({
|
|
4455
|
+
parsed,
|
|
4456
|
+
remotePath: parsed.skillPath,
|
|
4457
|
+
localDir: skillDir,
|
|
4458
|
+
relativePrefix: "",
|
|
4459
|
+
downloadedFiles
|
|
4460
|
+
});
|
|
4461
|
+
return {
|
|
4462
|
+
tempRoot,
|
|
4463
|
+
skillDir,
|
|
4464
|
+
commandOutput: [
|
|
4465
|
+
"Installer path: github-http",
|
|
4466
|
+
`Git repository: ${parsed.repoUrl}`,
|
|
4467
|
+
`Git path: ${parsed.skillPath}`,
|
|
4468
|
+
`Downloaded files: ${downloadedFiles.length}`
|
|
4469
|
+
].join("\n")
|
|
4470
|
+
};
|
|
4471
|
+
} catch (error) {
|
|
4472
|
+
rmSync3(tempRoot, { recursive: true, force: true });
|
|
4473
|
+
throw error;
|
|
4474
|
+
}
|
|
4475
|
+
}
|
|
4476
|
+
async downloadGithubDirectoryToPath(params) {
|
|
4477
|
+
const encodedPath = params.remotePath.split("/").filter(Boolean).map((segment) => encodeURIComponent(segment)).join("/");
|
|
4478
|
+
const apiUrl = new URL(`https://api.github.com/repos/${params.parsed.owner}/${params.parsed.repo}/contents/${encodedPath}`);
|
|
4479
|
+
if (params.parsed.ref) {
|
|
4480
|
+
apiUrl.searchParams.set("ref", params.parsed.ref);
|
|
4481
|
+
}
|
|
4482
|
+
const payload = await this.fetchJsonWithHeaders(apiUrl.toString(), {
|
|
4483
|
+
Accept: "application/vnd.github+json",
|
|
4484
|
+
"User-Agent": `${APP_NAME2}/${getPackageVersion()}`
|
|
4485
|
+
});
|
|
4486
|
+
if (!Array.isArray(payload)) {
|
|
4487
|
+
throw new Error(`GitHub path is not a directory: ${params.remotePath}`);
|
|
4488
|
+
}
|
|
4489
|
+
for (const entry of payload) {
|
|
4490
|
+
if (!entry || typeof entry !== "object") {
|
|
4491
|
+
continue;
|
|
4492
|
+
}
|
|
4493
|
+
const item = entry;
|
|
4494
|
+
const itemName = typeof item.name === "string" ? item.name.trim() : "";
|
|
4495
|
+
const itemPath = typeof item.path === "string" ? item.path.trim() : "";
|
|
4496
|
+
if (!itemName || !itemPath) {
|
|
4497
|
+
continue;
|
|
4498
|
+
}
|
|
4499
|
+
if (item.type === "dir") {
|
|
4500
|
+
const childLocalDir = join5(params.localDir, itemName);
|
|
4501
|
+
mkdirSync4(childLocalDir, { recursive: true });
|
|
4502
|
+
await this.downloadGithubDirectoryToPath({
|
|
4503
|
+
parsed: params.parsed,
|
|
4504
|
+
remotePath: itemPath,
|
|
4505
|
+
localDir: childLocalDir,
|
|
4506
|
+
relativePrefix: params.relativePrefix ? `${params.relativePrefix}/${itemName}` : itemName,
|
|
4507
|
+
downloadedFiles: params.downloadedFiles
|
|
4508
|
+
});
|
|
4509
|
+
continue;
|
|
4510
|
+
}
|
|
4511
|
+
if (item.type !== "file") {
|
|
4512
|
+
throw new Error(`Unsupported GitHub skill entry type: ${item.type ?? "unknown"}`);
|
|
4513
|
+
}
|
|
4514
|
+
if (!item.download_url) {
|
|
4515
|
+
throw new Error(`GitHub skill file missing download_url: ${itemPath}`);
|
|
4516
|
+
}
|
|
4517
|
+
const content = await this.fetchBinaryWithHeaders(item.download_url, {
|
|
4518
|
+
"User-Agent": `${APP_NAME2}/${getPackageVersion()}`
|
|
4519
|
+
});
|
|
4520
|
+
const localFile = join5(params.localDir, itemName);
|
|
4521
|
+
writeFileSync4(localFile, content);
|
|
4522
|
+
params.downloadedFiles.push(params.relativePrefix ? `${params.relativePrefix}/${itemName}` : itemName);
|
|
4523
|
+
}
|
|
4524
|
+
}
|
|
4525
|
+
async fetchJsonWithHeaders(url, headers) {
|
|
4526
|
+
const response = await fetch(url, { headers });
|
|
4527
|
+
if (!response.ok) {
|
|
4528
|
+
throw new Error(`HTTP ${response.status} when fetching ${url}`);
|
|
4529
|
+
}
|
|
4530
|
+
return await response.json();
|
|
4531
|
+
}
|
|
4532
|
+
async fetchBinaryWithHeaders(url, headers) {
|
|
4533
|
+
const response = await fetch(url, { headers });
|
|
4534
|
+
if (!response.ok) {
|
|
4535
|
+
throw new Error(`HTTP ${response.status} when downloading ${url}`);
|
|
4536
|
+
}
|
|
4537
|
+
const bytes = await response.arrayBuffer();
|
|
4538
|
+
return Buffer.from(bytes);
|
|
4539
|
+
}
|
|
4430
4540
|
parseMarketplaceGitSkillSource(source) {
|
|
4431
4541
|
const trimmed = source.trim();
|
|
4432
4542
|
if (!trimmed) {
|
|
@@ -4447,6 +4557,8 @@ var ServiceCommands = class {
|
|
|
4447
4557
|
throw new Error(`Unsupported GitHub skill source URL: ${source}`);
|
|
4448
4558
|
}
|
|
4449
4559
|
return {
|
|
4560
|
+
owner: owner2,
|
|
4561
|
+
repo: repo2,
|
|
4450
4562
|
repoUrl: `https://github.com/${owner2}/${repo2}.git`,
|
|
4451
4563
|
skillPath: pathParts2.join("/"),
|
|
4452
4564
|
ref: ref2
|
|
@@ -4466,6 +4578,8 @@ var ServiceCommands = class {
|
|
|
4466
4578
|
throw new Error(`Unsupported git skill source: ${source}`);
|
|
4467
4579
|
}
|
|
4468
4580
|
return {
|
|
4581
|
+
owner,
|
|
4582
|
+
repo,
|
|
4469
4583
|
repoUrl: `https://github.com/${owner}/${repo}.git`,
|
|
4470
4584
|
skillPath: pathParts.join("/"),
|
|
4471
4585
|
ref: ref && ref.trim().length > 0 ? ref.trim() : void 0
|
|
@@ -4628,7 +4742,7 @@ ${stderr}`.trim();
|
|
|
4628
4742
|
};
|
|
4629
4743
|
|
|
4630
4744
|
// src/cli/workspace.ts
|
|
4631
|
-
import { cpSync as cpSync2, existsSync as existsSync9, mkdirSync as mkdirSync5, readFileSync as readFileSync7, readdirSync as readdirSync2, rmSync as rmSync4, writeFileSync as
|
|
4745
|
+
import { cpSync as cpSync2, existsSync as existsSync9, mkdirSync as mkdirSync5, readFileSync as readFileSync7, readdirSync as readdirSync2, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
4632
4746
|
import { createRequire } from "module";
|
|
4633
4747
|
import { dirname as dirname2, join as join6, resolve as resolve8 } from "path";
|
|
4634
4748
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -4672,7 +4786,7 @@ var WorkspaceManager = class {
|
|
|
4672
4786
|
const raw = readFileSync7(templatePath, "utf-8");
|
|
4673
4787
|
const content = raw.replace(/\$\{APP_NAME\}/g, APP_NAME3);
|
|
4674
4788
|
mkdirSync5(dirname2(filePath), { recursive: true });
|
|
4675
|
-
|
|
4789
|
+
writeFileSync5(filePath, content);
|
|
4676
4790
|
created.push(entry.target);
|
|
4677
4791
|
}
|
|
4678
4792
|
const memoryDir = join6(workspace, "memory");
|
|
@@ -5240,7 +5354,7 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
|
|
|
5240
5354
|
const merged = history.concat(
|
|
5241
5355
|
rl.history ?? []
|
|
5242
5356
|
);
|
|
5243
|
-
|
|
5357
|
+
writeFileSync6(historyFile, merged.join("\n"));
|
|
5244
5358
|
process.exit(0);
|
|
5245
5359
|
});
|
|
5246
5360
|
let running = true;
|