nextclaw 0.9.22 → 0.9.23

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.
Files changed (2) hide show
  1. package/dist/cli/index.js +67 -3
  2. package/package.json +5 -5
package/dist/cli/index.js CHANGED
@@ -235,7 +235,8 @@ async function installMarketplaceSkill(options) {
235
235
  throw new Error(`Invalid marketplace file path: ${file.path}`);
236
236
  }
237
237
  mkdirSync2(dirname(targetPath), { recursive: true });
238
- writeFileSync2(targetPath, Buffer.from(file.contentBase64, "base64"));
238
+ const bytes = await fetchMarketplaceSkillFileBlob(apiBase, slug, file);
239
+ writeFileSync2(targetPath, bytes);
239
240
  }
240
241
  if (!existsSync2(join(destinationDir, "SKILL.md"))) {
241
242
  throw new Error(`Marketplace skill ${slug} does not include SKILL.md`);
@@ -362,7 +363,59 @@ async function fetchMarketplaceSkillFiles(apiBase, slug) {
362
363
  const message = payload.error?.message || `marketplace skill file fetch failed: ${response.status}`;
363
364
  throw new Error(message);
364
365
  }
365
- return payload.data;
366
+ if (!isRecord(payload.data) || !Array.isArray(payload.data.files)) {
367
+ throw new Error("Invalid marketplace skill file manifest response");
368
+ }
369
+ const files = payload.data.files.map((entry, index) => {
370
+ if (!isRecord(entry) || typeof entry.path !== "string" || entry.path.trim().length === 0) {
371
+ throw new Error(`Invalid marketplace skill file manifest at index ${index}`);
372
+ }
373
+ const normalized = {
374
+ path: entry.path.trim()
375
+ };
376
+ if (typeof entry.downloadPath === "string" && entry.downloadPath.trim().length > 0) {
377
+ normalized.downloadPath = entry.downloadPath.trim();
378
+ }
379
+ return normalized;
380
+ });
381
+ return { files };
382
+ }
383
+ async function fetchMarketplaceSkillFileBlob(apiBase, slug, file) {
384
+ const downloadUrl = resolveSkillFileDownloadUrl(apiBase, slug, file);
385
+ const response = await fetch(downloadUrl, {
386
+ headers: {
387
+ Accept: "application/octet-stream"
388
+ }
389
+ });
390
+ if (!response.ok) {
391
+ const message = await tryReadMarketplaceError(response);
392
+ throw new Error(message || `marketplace skill file download failed: ${response.status}`);
393
+ }
394
+ const arrayBuffer = await response.arrayBuffer();
395
+ return Buffer.from(arrayBuffer);
396
+ }
397
+ function resolveSkillFileDownloadUrl(apiBase, slug, file) {
398
+ const fallback = `${apiBase}/api/v1/skills/items/${encodeURIComponent(slug)}/files/blob?path=${encodeURIComponent(file.path)}`;
399
+ if (!file.downloadPath) {
400
+ return fallback;
401
+ }
402
+ if (file.downloadPath.startsWith("http://") || file.downloadPath.startsWith("https://")) {
403
+ return file.downloadPath;
404
+ }
405
+ const normalizedPath = file.downloadPath.startsWith("/") ? file.downloadPath : `/${file.downloadPath}`;
406
+ return `${apiBase}${normalizedPath}`;
407
+ }
408
+ async function tryReadMarketplaceError(response) {
409
+ const raw = await response.text();
410
+ if (!raw.trim()) {
411
+ return void 0;
412
+ }
413
+ try {
414
+ const payload = JSON.parse(raw);
415
+ return payload.error?.message;
416
+ } catch {
417
+ return void 0;
418
+ }
366
419
  }
367
420
  async function readMarketplaceEnvelope(response) {
368
421
  const raw = await response.text();
@@ -3149,7 +3202,7 @@ var GatewayAgentRuntimePool = class {
3149
3202
  await this.options.bus.publishOutbound({
3150
3203
  channel: message.channel,
3151
3204
  chatId: message.chatId,
3152
- content: `Sorry, I encountered an error: ${String(error)}`,
3205
+ content: `Sorry, I encountered an error: ${formatUserFacingError(error)}`,
3153
3206
  media: [],
3154
3207
  metadata: {}
3155
3208
  });
@@ -3385,6 +3438,17 @@ function parseCommandOptionValue(type, rawValue) {
3385
3438
  }
3386
3439
  return value;
3387
3440
  }
3441
+ function formatUserFacingError(error, maxChars = 320) {
3442
+ const raw = error instanceof Error ? error.message || error.name || "Unknown error" : String(error ?? "Unknown error");
3443
+ const normalized = raw.replace(/\s+/g, " ").trim();
3444
+ if (!normalized) {
3445
+ return "Unknown error";
3446
+ }
3447
+ if (normalized.length <= maxChars) {
3448
+ return normalized;
3449
+ }
3450
+ return `${normalized.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
3451
+ }
3388
3452
 
3389
3453
  // src/cli/commands/ui-chat-run-coordinator.ts
3390
3454
  import { existsSync as existsSync7, mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nextclaw",
3
- "version": "0.9.22",
3
+ "version": "0.9.23",
4
4
  "description": "Lightweight personal AI assistant with CLI, multi-provider routing, and channel integrations.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -38,10 +38,10 @@
38
38
  "dependencies": {
39
39
  "chokidar": "^3.6.0",
40
40
  "commander": "^12.1.0",
41
- "@nextclaw/core": "0.7.5",
42
- "@nextclaw/runtime": "0.1.4",
43
- "@nextclaw/server": "0.6.9",
44
- "@nextclaw/openclaw-compat": "0.2.4"
41
+ "@nextclaw/core": "0.7.6",
42
+ "@nextclaw/runtime": "0.1.5",
43
+ "@nextclaw/openclaw-compat": "0.2.5",
44
+ "@nextclaw/server": "0.6.10"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/node": "^20.17.6",