@hasna/skills 0.1.45 → 0.1.47

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/bin/index.js CHANGED
@@ -9553,7 +9553,7 @@ Learn more about this warning here: https://reactjs.org/link/legacy-context`, so
9553
9553
 
9554
9554
  ` + ("" + errorBoundaryMessage);
9555
9555
  console["error"](combinedMessage);
9556
- }
9556
+ } else {}
9557
9557
  } catch (e) {
9558
9558
  setTimeout(function() {
9559
9559
  throw e;
@@ -18037,7 +18037,7 @@ var require_backend = __commonJS((exports, module) => {
18037
18037
  987: (module2, __unused_webpack_exports, __webpack_require__2) => {
18038
18038
  if (true) {
18039
18039
  module2.exports = __webpack_require__2(786);
18040
- }
18040
+ } else {}
18041
18041
  },
18042
18042
  126: (__unused_webpack_module, exports2, __webpack_require__2) => {
18043
18043
  var process3 = __webpack_require__2(169);
@@ -18487,7 +18487,7 @@ var require_backend = __commonJS((exports, module) => {
18487
18487
  189: (module2, __unused_webpack_exports, __webpack_require__2) => {
18488
18488
  if (true) {
18489
18489
  module2.exports = __webpack_require__2(126);
18490
- }
18490
+ } else {}
18491
18491
  },
18492
18492
  206: function(module2, exports2, __webpack_require__2) {
18493
18493
  var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
@@ -18502,7 +18502,7 @@ var require_backend = __commonJS((exports, module) => {
18502
18502
  (function(root, factory) {
18503
18503
  if (true) {
18504
18504
  __WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__2(430)], __WEBPACK_AMD_DEFINE_FACTORY__ = factory, __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports2, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module2.exports = __WEBPACK_AMD_DEFINE_RESULT__);
18505
- }
18505
+ } else {}
18506
18506
  })(this, function ErrorStackParser(StackFrame) {
18507
18507
  var FIREFOX_SAFARI_STACK_REGEXP = /(^|@)\S+:\d+/;
18508
18508
  var CHROME_IE_STACK_REGEXP = /^\s*at .*(\S+:\d+|\(native\))/m;
@@ -19198,7 +19198,7 @@ var require_backend = __commonJS((exports, module) => {
19198
19198
  (function(root, factory) {
19199
19199
  if (true) {
19200
19200
  __WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = factory, __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports2, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module2.exports = __WEBPACK_AMD_DEFINE_RESULT__);
19201
- }
19201
+ } else {}
19202
19202
  })(this, function() {
19203
19203
  function _isNumber(n) {
19204
19204
  return !isNaN(parseFloat(n)) && isFinite(n);
@@ -24572,7 +24572,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
24572
24572
  var suffix = "";
24573
24573
  if (true) {
24574
24574
  suffix = " (<anonymous>)";
24575
- }
24575
+ } else {}
24576
24576
  return `
24577
24577
  ` + prefix + name + suffix;
24578
24578
  }
@@ -27301,7 +27301,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
27301
27301
  hasChanges = true;
27302
27302
  updateMostRecentlyInspectedElementIfNecessary(devtoolsInstance.id);
27303
27303
  }
27304
- }
27304
+ } else {}
27305
27305
  }
27306
27306
  } catch (err) {
27307
27307
  _iterator2.e(err);
@@ -29080,7 +29080,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
29080
29080
  if (contentFiber === null) {
29081
29081
  throw new Error("There should always be an Offscreen Fiber child in a hydrated Suspense boundary.");
29082
29082
  }
29083
- }
29083
+ } else {}
29084
29084
  var _isTimedOut = fiber.memoizedState !== null;
29085
29085
  if (!_isTimedOut) {
29086
29086
  newSuspenseNode.rects = measureInstance(newInstance);
@@ -29114,7 +29114,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
29114
29114
  if (_contentFiber === null) {
29115
29115
  throw new Error("There should always be an Offscreen Fiber child in a hydrated Suspense boundary.");
29116
29116
  }
29117
- }
29117
+ } else {}
29118
29118
  var suspenseState = fiber.memoizedState;
29119
29119
  var _isTimedOut3 = suspenseState !== null;
29120
29120
  if (!_isTimedOut3) {
@@ -29214,7 +29214,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
29214
29214
  trackThrownPromisesFromRetryCache(newSuspenseNode, fiber.stateNode);
29215
29215
  mountSuspenseChildrenRecursively(_contentFiber2, traceNearestHostComponentUpdate, stashedSuspenseParent, stashedSuspensePrevious, stashedSuspenseRemaining);
29216
29216
  shouldPopSuspenseNode = false;
29217
- }
29217
+ } else {}
29218
29218
  } else {
29219
29219
  if (fiber.child !== null) {
29220
29220
  mountChildrenRecursively(fiber.child, traceNearestHostComponentUpdate);
@@ -29800,7 +29800,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
29800
29800
  shouldPopSuspenseNode = false;
29801
29801
  } else if (previousHydrated && !nextHydrated) {
29802
29802
  throw new Error("Encountered a dehydrated Suspense boundary that was previously hydrated.");
29803
- }
29803
+ } else {}
29804
29804
  } else {
29805
29805
  if (nextFiber.child !== prevFiber.child) {
29806
29806
  updateFlags |= updateChildrenRecursively(nextFiber.child, prevFiber.child, traceNearestHostComponentUpdate);
@@ -29846,8 +29846,8 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
29846
29846
  recordResetChildren(fiberInstance);
29847
29847
  }
29848
29848
  updateFlags &= ~ShouldResetChildren;
29849
- }
29850
- }
29849
+ } else {}
29850
+ } else {}
29851
29851
  if ((updateFlags & ShouldResetSuspenseChildren) !== NoUpdate) {
29852
29852
  if (fiberInstance !== null && fiberInstance.kind === FIBER_INSTANCE) {
29853
29853
  var _suspenseNode3 = fiberInstance.suspenseNode;
@@ -29855,7 +29855,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
29855
29855
  recordResetSuspenseChildren(_suspenseNode3);
29856
29856
  updateFlags &= ~ShouldResetSuspenseChildren;
29857
29857
  }
29858
- }
29858
+ } else {}
29859
29859
  }
29860
29860
  if ((updateFlags & ShouldResetParentSuspenseChildren) !== NoUpdate) {
29861
29861
  if (fiberInstance !== null && fiberInstance.kind === FIBER_INSTANCE) {
@@ -29864,7 +29864,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
29864
29864
  updateFlags &= ~ShouldResetParentSuspenseChildren;
29865
29865
  updateFlags |= ShouldResetSuspenseChildren;
29866
29866
  }
29867
- }
29867
+ } else {}
29868
29868
  }
29869
29869
  return updateFlags;
29870
29870
  } finally {
@@ -32928,7 +32928,7 @@ The error thrown in the component is:
32928
32928
  rendererInterface = renderer_attach(hook, id, renderer, global2, shouldStartProfilingNow, profilingSettings);
32929
32929
  } else if (renderer.ComponentTree) {
32930
32930
  rendererInterface = legacy_renderer_attach(hook, id, renderer, global2);
32931
- }
32931
+ } else {}
32932
32932
  }
32933
32933
  return rendererInterface;
32934
32934
  }
@@ -35811,7 +35811,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
35811
35811
  this._exitCallback = (err) => {
35812
35812
  if (err.code !== "commander.executeSubCommandAsync") {
35813
35813
  throw err;
35814
- }
35814
+ } else {}
35815
35815
  };
35816
35816
  }
35817
35817
  return this;
@@ -36860,7 +36860,7 @@ var package_default;
36860
36860
  var init_package = __esm(() => {
36861
36861
  package_default = {
36862
36862
  name: "@hasna/skills",
36863
- version: "0.1.45",
36863
+ version: "0.1.47",
36864
36864
  description: "Skills library for AI coding agents",
36865
36865
  type: "module",
36866
36866
  bin: {
@@ -36929,7 +36929,7 @@ var init_package = __esm(() => {
36929
36929
  typescript: "^5"
36930
36930
  },
36931
36931
  dependencies: {
36932
- "@hasna/events": "^0.1.3",
36932
+ "@hasna/events": "^0.1.7",
36933
36933
  "@modelcontextprotocol/sdk": "^1.26.0",
36934
36934
  chalk: "^5.3.0",
36935
36935
  commander: "^12.1.0",
@@ -37993,7 +37993,8 @@ var init_skill_aliases = __esm(() => {
37993
37993
  "pdf-reader": "read-pdf",
37994
37994
  "generate-image": "image",
37995
37995
  "image-generator": "image",
37996
- "create-blog-article": "blog-article"
37996
+ "create-blog-article": "blog-article",
37997
+ "skill-diff": "diff-viewer"
37997
37998
  };
37998
37999
  });
37999
38000
 
@@ -38410,7 +38411,7 @@ var init_pricing = __esm(() => {
38410
38411
  { slug: "brand-kit", displayName: "Brand Kit", tier: "premium", costCents: 400, providers: ["hosted"], description: "Hosted brand kit with logo usage, palette, typography, brand voice, sample applications, Markdown guide, PDF guide, and SVG assets" },
38411
38412
  { slug: "generate-book-cover", displayName: "Book Cover", tier: "premium", costCents: 20, providers: ["gpt-image-2"], description: "Professional book cover design from title and genre" },
38412
38413
  { slug: "remove-background", displayName: "Remove Background", tier: "premium", costCents: 10, providers: ["gemini-3-pro"], description: "AI-powered background removal from images" },
38413
- { slug: "transcript", displayName: "Transcript", tier: "premium", costCents: 10, providers: ["whisper"], description: "Audio/video transcription with timestamps" },
38414
+ { slug: "transcript", displayName: "Transcript", tier: "premium", costCents: 10, providers: ["openai", "elevenlabs", "deepgram", "hosted"], description: "Audio/video transcription with timestamps, diarization, and URL support" },
38414
38415
  { slug: "webcrawling", displayName: "Web Crawling", tier: "premium", costCents: 5, providers: ["firecrawl"], description: "Structured web page crawling and extraction" },
38415
38416
  { slug: "browse", displayName: "Browse", tier: "premium", costCents: 5, providers: ["browser"], description: "Web browsing and page interaction" },
38416
38417
  { slug: "read-pdf", displayName: "Read PDF", tier: "premium", costCents: 5, providers: ["cerebras"], description: "Hosted PDF extraction and structured content analysis" },
@@ -39089,12 +39090,47 @@ function ensurePortableSkillFiles(skillPath, manifest) {
39089
39090
  writeFileSync2(join5(skillPath, "skill.json"), renderSkillJson(next));
39090
39091
  if (!existsSync5(join5(skillPath, "AGENTS.md")))
39091
39092
  writeFileSync2(join5(skillPath, "AGENTS.md"), renderAgentsMd(next));
39092
- if (!existsSync5(join5(skillPath, "package.json")))
39093
- writeFileSync2(join5(skillPath, "package.json"), renderPackageJson(next));
39093
+ ensurePackageJson(skillPath, next);
39094
39094
  if (!existsSync5(join5(skillPath, "tsconfig.json")))
39095
39095
  writeFileSync2(join5(skillPath, "tsconfig.json"), renderTsconfig());
39096
39096
  return readPortableSkillManifest(skillPath, next.name);
39097
39097
  }
39098
+ function ensurePackageJson(skillPath, manifest) {
39099
+ const pkgPath = join5(skillPath, "package.json");
39100
+ const first = manifest.commands[0] ?? { name: manifest.name, entry: "src/index.ts" };
39101
+ const commandName = normalizePortableSkillName(first.name || manifest.name);
39102
+ const entry = (first.entry ?? "src/index.ts").replace(/^\.\//, "");
39103
+ if (!existsSync5(pkgPath)) {
39104
+ writeFileSync2(pkgPath, renderPackageJson(manifest));
39105
+ return;
39106
+ }
39107
+ const existing = readJsonObject(pkgPath);
39108
+ const bin = {};
39109
+ if (isRecord(existing.bin)) {
39110
+ for (const [name, value] of Object.entries(existing.bin)) {
39111
+ if (typeof value === "string" && value.trim())
39112
+ bin[normalizePortableSkillName(name)] = value.replace(/^\.\//, "");
39113
+ }
39114
+ } else {
39115
+ const binEntry = stringValue(existing.bin);
39116
+ if (binEntry)
39117
+ bin[manifest.name] = binEntry.replace(/^\.\//, "");
39118
+ }
39119
+ bin[commandName] = entry;
39120
+ const scripts = isRecord(existing.scripts) ? { ...existing.scripts } : {};
39121
+ if (!stringValue(scripts.dev))
39122
+ scripts.dev = `bun run ${entry}`;
39123
+ writeFileSync2(pkgPath, `${JSON.stringify({
39124
+ ...existing,
39125
+ name: manifest.name,
39126
+ version: manifest.version,
39127
+ description: manifest.description,
39128
+ type: stringValue(existing.type) ?? "module",
39129
+ bin,
39130
+ scripts
39131
+ }, null, 2)}
39132
+ `);
39133
+ }
39098
39134
  function copySkillDirectory(source, destination) {
39099
39135
  mkdirSync2(destination, { recursive: true });
39100
39136
  cpSync(source, destination, {
@@ -40581,9 +40617,9 @@ var init_media_processing = __esm(() => {
40581
40617
  {
40582
40618
  name: "transcript",
40583
40619
  displayName: "Transcript",
40584
- description: "Generate transcripts from audio and video files with timestamps",
40620
+ description: "Transcribe audio, video, and media URLs with OpenAI GPT-4o, ElevenLabs Scribe v2, DeepGram, or hosted runtime",
40585
40621
  category: "Media Processing",
40586
- tags: ["transcript", "audio", "video", "speech-to-text"]
40622
+ tags: ["transcript", "audio", "video", "speech-to-text", "diarization", "youtube"]
40587
40623
  },
40588
40624
  {
40589
40625
  name: "video-cut-suggester",
@@ -54456,7 +54492,7 @@ function finalize(ctx, schema) {
54456
54492
  result2.$schema = "http://json-schema.org/draft-07/schema#";
54457
54493
  } else if (ctx.target === "draft-04") {
54458
54494
  result2.$schema = "http://json-schema.org/draft-04/schema#";
54459
- } else if (ctx.target === "openapi-3.0") {}
54495
+ } else if (ctx.target === "openapi-3.0") {} else {}
54460
54496
  if (ctx.external?.uri) {
54461
54497
  const id = ctx.external.registry.get(schema)?.id;
54462
54498
  if (!id)
@@ -54721,7 +54757,7 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
54721
54757
  if (val === undefined) {
54722
54758
  if (ctx.unrepresentable === "throw") {
54723
54759
  throw new Error("Literal `undefined` cannot be represented in JSON Schema");
54724
- }
54760
+ } else {}
54725
54761
  } else if (typeof val === "bigint") {
54726
54762
  if (ctx.unrepresentable === "throw") {
54727
54763
  throw new Error("BigInt literals cannot be represented in JSON Schema");
@@ -58051,30 +58087,119 @@ var init_install = __esm(() => {
58051
58087
  init_installer();
58052
58088
  });
58053
58089
 
58090
+ // src/lib/compact-output.ts
58091
+ function truncateText(value, maxChars = 96) {
58092
+ const text = String(value ?? "").replace(/\s+/g, " ").trim();
58093
+ if (text.length <= maxChars)
58094
+ return text;
58095
+ return `${text.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
58096
+ }
58097
+ function previewText(value, maxChars = DEFAULT_PREVIEW_CHARS) {
58098
+ const text = String(value ?? "");
58099
+ return {
58100
+ text: text.length > maxChars ? `${text.slice(0, Math.max(0, maxChars - 3))}...` : text,
58101
+ length: text.length,
58102
+ truncated: text.length > maxChars
58103
+ };
58104
+ }
58105
+ function parsePageLimit(value, fallback, options = {}) {
58106
+ const max2 = options.max ?? MAX_PAGE_LIMIT;
58107
+ if (typeof value === "string" && options.allowAll && value.trim().toLowerCase() === "all") {
58108
+ return Number.POSITIVE_INFINITY;
58109
+ }
58110
+ const parsed = typeof value === "number" ? value : Number.parseInt(value ?? "", 10);
58111
+ if (!Number.isFinite(parsed))
58112
+ return fallback;
58113
+ if (options.allowAll && parsed === 0)
58114
+ return Number.POSITIVE_INFINITY;
58115
+ if (parsed <= 0)
58116
+ return fallback;
58117
+ return Math.min(parsed, max2);
58118
+ }
58119
+ function parsePageOffset(value, fallback = 0) {
58120
+ const parsed = typeof value === "number" ? value : Number.parseInt(value ?? "", 10);
58121
+ if (!Number.isFinite(parsed) || parsed < 0)
58122
+ return fallback;
58123
+ return parsed;
58124
+ }
58125
+ function paginate(items, options) {
58126
+ const offset = Math.min(parsePageOffset(options.offset), items.length);
58127
+ const effectiveLimit = Number.isFinite(options.limit) ? Math.max(0, Math.min(options.limit, MAX_PAGE_LIMIT)) : Math.max(0, items.length - offset);
58128
+ const pageItems = items.slice(offset, offset + effectiveLimit);
58129
+ const nextOffset = offset + pageItems.length < items.length ? offset + pageItems.length : null;
58130
+ return {
58131
+ items: pageItems,
58132
+ total: items.length,
58133
+ offset,
58134
+ limit: effectiveLimit,
58135
+ hasMore: nextOffset !== null,
58136
+ nextOffset
58137
+ };
58138
+ }
58139
+ function showingLabel(total, shown, offset) {
58140
+ if (offset > 0 || shown < total)
58141
+ return `showing ${shown} of ${total}, cursor ${offset}`;
58142
+ return String(total);
58143
+ }
58144
+ function compactRunRecord(run) {
58145
+ if (!run || typeof run !== "object")
58146
+ return {};
58147
+ return {
58148
+ id: run.id,
58149
+ skill: run.skill,
58150
+ status: run.status,
58151
+ startedAt: run.startedAt,
58152
+ ...run.completedAt ? { completedAt: run.completedAt } : {},
58153
+ ...run.remoteRunId ? { remoteRunId: run.remoteRunId } : {},
58154
+ ...run.costCents !== undefined ? { costCents: run.costCents } : {},
58155
+ ...run.error ? { error: truncateText(run.error, 240) } : {},
58156
+ artifactCount: Array.isArray(run.artifacts) ? run.artifacts.length : 0,
58157
+ paths: run.paths
58158
+ };
58159
+ }
58160
+ function compactRemoteRun(run) {
58161
+ if (!run || typeof run !== "object")
58162
+ return {};
58163
+ return {
58164
+ ...run.contractVersion !== undefined ? { contractVersion: run.contractVersion } : {},
58165
+ id: run.id,
58166
+ skill: run.skill ?? run.requestedSlug,
58167
+ status: run.status,
58168
+ ...run.correlationId ? { correlationId: run.correlationId } : {},
58169
+ ...run.createdAt ? { createdAt: run.createdAt } : {},
58170
+ ...run.startedAt ? { startedAt: run.startedAt } : {},
58171
+ ...run.completedAt ? { completedAt: run.completedAt } : {},
58172
+ ...run.error || run.errorMessage ? { error: truncateText(run.error ?? run.errorMessage, 240) } : {}
58173
+ };
58174
+ }
58175
+ var DEFAULT_LIST_LIMIT = 30, DEFAULT_SEARCH_LIMIT = 20, DEFAULT_TAG_LIMIT = 80, DEFAULT_MCP_LIMIT = 25, MAX_PAGE_LIMIT = 200, DEFAULT_PREVIEW_CHARS = 600;
58176
+
58054
58177
  // src/cli/commands/list.ts
58055
58178
  var exports_list = {};
58056
58179
  __export(exports_list, {
58057
58180
  registerBrowse: () => registerBrowse
58058
58181
  });
58059
58182
  function registerBrowse(parent) {
58060
- parent.command("list").alias("ls").option("-c, --category <category>", "Filter by category").option("-p, --pinned", "Show only pinned skills", false).option("-t, --tags <tags>", "Filter by comma-separated tags (OR logic, case-insensitive)").option("--all", "Show the full skill registry instead of the default basic set", false).option("--remote", "Use remote registry from SKILLS_API_URL or config apiUrl", false).option("--json", "Output as JSON", false).option("--brief", "One line per skill: name \u2014 description [category]", false).option("--format <format>", "Output format: compact (names only) or csv (name,category,price,description)").action((options) => {
58183
+ parent.command("list").alias("ls").option("-c, --category <category>", "Filter by category").option("-p, --pinned", "Show only pinned skills", false).option("-t, --tags <tags>", "Filter by comma-separated tags (OR logic, case-insensitive)").option("--all", "Show the full skill registry instead of the default basic set", false).option("--remote", "Use remote registry from SKILLS_API_URL or config apiUrl", false).option("--json", "Output as JSON", false).option("--brief", "One line per skill: name \u2014 description [category]", false).option("--format <format>", "Output format: compact (names only) or csv (name,category,price,description)").option("--limit <n>", "Maximum rows to print for human output (default: 30, use 0 or all for every row)").option("--cursor <n>", "Numeric offset for human-output pagination", "0").option("--verbose", "Show longer descriptions and tags in human output", false).action((options) => {
58061
58184
  return handleList(options).catch(handleBrowseError);
58062
58185
  });
58063
- parent.command("search").alias("s").argument("<query>", "Search term").option("--json", "Output as JSON", false).option("--brief", "One line per skill: name \u2014 description [category]", false).option("--format <format>", "Output format: compact (names only) or csv (name,category,price,description)").option("-c, --category <category>", "Filter results by category").option("-t, --tags <tags>", "Filter results by comma-separated tags (OR logic, case-insensitive)").option("--all", "Search the full skill registry instead of the default basic set", false).option("--remote", "Use remote registry from SKILLS_API_URL or config apiUrl", false).description("Search for skills").action((query, options) => {
58186
+ parent.command("search").alias("s").argument("<query>", "Search term").option("--json", "Output as JSON", false).option("--brief", "One line per skill: name \u2014 description [category]", false).option("--format <format>", "Output format: compact (names only) or csv (name,category,price,description)").option("-c, --category <category>", "Filter results by category").option("-t, --tags <tags>", "Filter results by comma-separated tags (OR logic, case-insensitive)").option("--all", "Search the full skill registry instead of the default basic set", false).option("--remote", "Use remote registry from SKILLS_API_URL or config apiUrl", false).option("--limit <n>", "Maximum rows to print for human output (default: 20, use 0 or all for every row)").option("--cursor <n>", "Numeric offset for human-output pagination", "0").option("--verbose", "Show longer descriptions and tags in human output", false).description("Search for skills").action((query, options) => {
58064
58187
  return handleSearch(query, options).catch(handleBrowseError);
58065
58188
  });
58066
58189
  parent.command("categories").option("--json", "Output as JSON", false).option("--remote", "Use remote registry from SKILLS_API_URL or config apiUrl", false).description("List all categories").action((options) => {
58067
58190
  return handleCategories(options).catch(handleBrowseError);
58068
58191
  });
58069
- parent.command("tags").option("--json", "Output as JSON", false).option("--remote", "Use remote registry from SKILLS_API_URL or config apiUrl", false).description("List all unique tags with counts").action((options) => {
58192
+ parent.command("tags").option("--json", "Output as JSON", false).option("--remote", "Use remote registry from SKILLS_API_URL or config apiUrl", false).option("--limit <n>", "Maximum rows to print for human output (default: 80, use 0 or all for every row)").option("--cursor <n>", "Numeric offset for human-output pagination", "0").description("List all unique tags with counts").action((options) => {
58070
58193
  return handleTags(options).catch(handleBrowseError);
58071
58194
  });
58072
58195
  }
58073
58196
  function formatBrief(skill) {
58074
- return `${skill.name} \u2014 ${skill.description} (${publicDiscoveryPriceLabel(skill)}) [${skill.category}]`;
58197
+ return `${skill.name} \u2014 ${truncateText(skill.description, 110)} (${publicDiscoveryPriceLabel(skill)}) [${skill.category}]`;
58075
58198
  }
58076
- function formatSkillLine(skill) {
58077
- return ` ${source_default.cyan(skill.name)}${skill.source === "custom" ? source_default.yellow(" [custom]") : ""} ${source_default.dim(`(${publicDiscoveryPriceLabel(skill)})`)} - ${skill.description}`;
58199
+ function formatSkillLine(skill, options = {}) {
58200
+ const description = truncateText(skill.description, options.verbose ? 180 : 88);
58201
+ const tags = options.verbose && skill.tags.length ? source_default.dim(` tags: ${skill.tags.join(", ")}`) : "";
58202
+ return ` ${source_default.cyan(skill.name)}${skill.source === "custom" ? source_default.yellow(" [custom]") : ""} ${source_default.dim(`[${skill.category}]`)} ${source_default.dim(`(${publicDiscoveryPriceLabel(skill)})`)} - ${description}${tags}`;
58078
58203
  }
58079
58204
  function enrichDiscovery(skills) {
58080
58205
  return skills.map(getPublicSkillDiscovery);
@@ -58114,6 +58239,8 @@ async function handleList(options) {
58114
58239
  const fmt = !options.json ? options.format : undefined;
58115
58240
  const profile = options.all ? "all" : "basic";
58116
58241
  const registry2 = await getBrowseRegistry(options);
58242
+ const limit = parsePageLimit(options.limit, DEFAULT_LIST_LIMIT, { allowAll: true });
58243
+ const offset = parsePageOffset(options.cursor);
58117
58244
  if (options.pinned) {
58118
58245
  const installed = getInstalledSkills();
58119
58246
  if (options.json) {
@@ -58137,14 +58264,16 @@ async function handleList(options) {
58137
58264
  }
58138
58265
  const meta3 = getInstallMeta();
58139
58266
  const registry3 = loadRegistry();
58267
+ const page2 = paginate(installed, { limit, offset });
58140
58268
  console.log(source_default.bold(`
58141
- Pinned skills (${installed.length}):
58269
+ Pinned skills (${showingLabel(installed.length, page2.items.length, page2.offset)}):
58142
58270
  `));
58143
- for (const name of installed) {
58271
+ for (const name of page2.items) {
58144
58272
  const m = meta3.skills[name];
58145
58273
  const s = registry3.find((r) => r.name === name);
58146
58274
  console.log(` ${source_default.cyan(name)}${s?.source === "custom" ? source_default.yellow(" [custom]") : ""} ${m?.version ? source_default.dim(`v${m.version}`) : ""} ${m?.installedAt ? source_default.dim(new Date(m.installedAt).toLocaleDateString()) : ""}`);
58147
58275
  }
58276
+ printPageHint(page2, "skills list --pinned");
58148
58277
  return;
58149
58278
  }
58150
58279
  const tagFilter = options.tags ? options.tags.split(",").map((t) => t.trim().toLowerCase()).filter(Boolean) : null;
@@ -58165,16 +58294,19 @@ Available: ${categories.join(", ")}`);
58165
58294
  await writeJson(output, 2);
58166
58295
  return;
58167
58296
  }
58297
+ const page2 = paginate(output, { limit, offset });
58168
58298
  if (brief) {
58169
- for (const s of output)
58299
+ for (const s of page2.items)
58170
58300
  console.log(formatBrief(s));
58301
+ printPageHint(page2, listCommand(options));
58171
58302
  return;
58172
58303
  }
58173
58304
  console.log(source_default.bold(`
58174
- ${category} (${skills.length}):
58305
+ ${category} (${showingLabel(output.length, page2.items.length, page2.offset)}):
58175
58306
  `));
58176
- for (const s of output)
58177
- console.log(formatSkillLine(s));
58307
+ for (const s of page2.items)
58308
+ console.log(formatSkillLine(s, { verbose: options.verbose }));
58309
+ printSkillHint(page2, listCommand(options));
58178
58310
  return;
58179
58311
  }
58180
58312
  if (tagFilter) {
@@ -58184,16 +58316,19 @@ ${category} (${skills.length}):
58184
58316
  await writeJson(output, 2);
58185
58317
  return;
58186
58318
  }
58319
+ const page2 = paginate(output, { limit, offset });
58187
58320
  if (brief) {
58188
- for (const s of output)
58321
+ for (const s of page2.items)
58189
58322
  console.log(formatBrief(s));
58323
+ printPageHint(page2, listCommand(options));
58190
58324
  return;
58191
58325
  }
58192
58326
  console.log(source_default.bold(`
58193
- Skills matching tags [${tagFilter.join(", ")}] (${skills.length}):
58327
+ Skills matching tags [${tagFilter.join(", ")}] (${showingLabel(output.length, page2.items.length, page2.offset)}):
58194
58328
  `));
58195
- for (const s of output)
58196
- console.log(` ${source_default.cyan(s.name)}${s.source === "custom" ? source_default.yellow(" [custom]") : ""} ${source_default.dim(`[${s.category}]`)} ${source_default.dim(`(${publicDiscoveryPriceLabel(s)})`)} - ${s.description}`);
58329
+ for (const s of page2.items)
58330
+ console.log(formatSkillLine(s, { verbose: options.verbose }));
58331
+ printSkillHint(page2, listCommand(options));
58197
58332
  return;
58198
58333
  }
58199
58334
  const allSkills = enrichDiscovery(registry2);
@@ -58215,28 +58350,21 @@ Skills matching tags [${tagFilter.join(", ")}] (${skills.length}):
58215
58350
  return;
58216
58351
  }
58217
58352
  if (brief) {
58218
- for (const s of [...allSkills].sort((a, b) => a.category.localeCompare(b.category) || a.name.localeCompare(b.name)))
58353
+ const sorted2 = [...allSkills].sort((a, b) => a.category.localeCompare(b.category) || a.name.localeCompare(b.name));
58354
+ const page2 = paginate(sorted2, { limit, offset });
58355
+ for (const s of page2.items)
58219
58356
  console.log(formatBrief(s));
58357
+ printPageHint(page2, listCommand(options));
58220
58358
  return;
58221
58359
  }
58360
+ const sorted = [...allSkills].sort((a, b) => a.category.localeCompare(b.category) || a.name.localeCompare(b.name));
58361
+ const page = paginate(sorted, { limit, offset });
58222
58362
  console.log(source_default.bold(`
58223
- Available ${profile === "basic" ? "default " : ""}skills (${allSkills.length}):
58363
+ Available ${profile === "basic" ? "default " : ""}skills (${showingLabel(allSkills.length, page.items.length, page.offset)}):
58224
58364
  `));
58225
- for (const category of registryCategories(allSkills)) {
58226
- const skills = allSkills.filter((s) => s.category === category);
58227
- if (skills.length === 0)
58228
- continue;
58229
- console.log(source_default.bold(`${category} (${skills.length}):`));
58230
- for (const s of skills)
58231
- console.log(formatSkillLine(s));
58232
- console.log();
58233
- }
58234
- const customUncategorized = allSkills.filter((s) => s.source === "custom" && !CATEGORIES.includes(s.category));
58235
- if (customUncategorized.length > 0) {
58236
- console.log(source_default.bold(`Custom (${customUncategorized.length}):`));
58237
- for (const s of customUncategorized)
58238
- console.log(` ${source_default.yellow(s.name)} ${source_default.dim(`(${publicDiscoveryPriceLabel(s)})`)} - ${s.description}`);
58239
- }
58365
+ for (const s of page.items)
58366
+ console.log(formatSkillLine(s, { verbose: options.verbose }));
58367
+ printSkillHint(page, listCommand(options));
58240
58368
  }
58241
58369
  async function handleSearch(query, options) {
58242
58370
  const registry2 = await getBrowseRegistry(options);
@@ -58283,19 +58411,22 @@ Available: ${categories.join(", ")}`);
58283
58411
  }
58284
58412
  return;
58285
58413
  }
58414
+ const limit = parsePageLimit(options.limit, DEFAULT_SEARCH_LIMIT, { allowAll: true });
58415
+ const offset = parsePageOffset(options.cursor);
58416
+ const page = paginate(output, { limit, offset });
58286
58417
  if (brief) {
58287
- for (const s of output)
58418
+ for (const s of page.items)
58288
58419
  console.log(formatBrief(s));
58420
+ printPageHint(page, searchCommand(query, options));
58289
58421
  return;
58290
58422
  }
58291
58423
  console.log(source_default.bold(`
58292
- Found ${output.length} skill(s):
58424
+ Found ${skillCountLabel(output.length, page.items.length, page.offset)} for "${query}":
58293
58425
  `));
58294
- for (const s of output) {
58295
- console.log(` ${source_default.cyan(s.name)} ${source_default.dim(`[${s.category}]`)}`);
58296
- console.log(` ${source_default.dim("Price:")} ${publicDiscoveryPriceLabel(s)}`);
58297
- console.log(` ${s.description}`);
58426
+ for (const s of page.items) {
58427
+ console.log(formatSkillLine(s, { verbose: options.verbose }));
58298
58428
  }
58429
+ printSkillHint(page, searchCommand(query, options));
58299
58430
  }
58300
58431
  async function handleCategories(options) {
58301
58432
  const registry2 = await getBrowseRegistry({ all: true, remote: options.remote });
@@ -58324,11 +58455,60 @@ async function handleTags(options) {
58324
58455
  await writeJson(sorted, 2);
58325
58456
  return;
58326
58457
  }
58458
+ const page = paginate(sorted, {
58459
+ limit: parsePageLimit(options.limit, DEFAULT_TAG_LIMIT, { allowAll: true }),
58460
+ offset: parsePageOffset(options.cursor)
58461
+ });
58327
58462
  console.log(source_default.bold(`
58328
- Tags:
58463
+ Tags: ${showingLabel(sorted.length, page.items.length, page.offset)}
58329
58464
  `));
58330
- for (const { name, count } of sorted)
58465
+ for (const { name, count } of page.items)
58331
58466
  console.log(` ${source_default.cyan(name)} (${count})`);
58467
+ printPageHint(page, `skills tags${options.remote ? " --remote" : ""}`);
58468
+ }
58469
+ function printSkillHint(page, command) {
58470
+ printPageHint(page, command);
58471
+ console.log(source_default.dim(`Details: skills show <name> or rerun with --verbose. Use --json for the full machine-readable payload.`));
58472
+ }
58473
+ function printPageHint(page, command) {
58474
+ if (!page.hasMore || page.nextOffset === null)
58475
+ return;
58476
+ console.log(source_default.dim(`
58477
+ Next: ${command} --cursor ${page.nextOffset} --limit ${page.limit}`));
58478
+ }
58479
+ function listCommand(options) {
58480
+ const parts = ["skills list"];
58481
+ if (options.all)
58482
+ parts.push("--all");
58483
+ if (options.remote)
58484
+ parts.push("--remote");
58485
+ if (options.category)
58486
+ parts.push("--category", quoteArg(options.category));
58487
+ if (options.tags)
58488
+ parts.push("--tags", quoteArg(options.tags));
58489
+ if (options.pinned)
58490
+ parts.push("--pinned");
58491
+ return parts.join(" ");
58492
+ }
58493
+ function searchCommand(query, options) {
58494
+ const parts = ["skills search", quoteArg(query)];
58495
+ if (options.all)
58496
+ parts.push("--all");
58497
+ if (options.remote)
58498
+ parts.push("--remote");
58499
+ if (options.category)
58500
+ parts.push("--category", quoteArg(options.category));
58501
+ if (options.tags)
58502
+ parts.push("--tags", quoteArg(options.tags));
58503
+ return parts.join(" ");
58504
+ }
58505
+ function quoteArg(value) {
58506
+ return value.includes(" ") ? JSON.stringify(value) : value;
58507
+ }
58508
+ function skillCountLabel(total, shown, offset) {
58509
+ if (offset > 0 || shown < total)
58510
+ return `${shown} of ${total} skill(s), cursor ${offset}`;
58511
+ return `${total} skill(s)`;
58332
58512
  }
58333
58513
  var init_list = __esm(() => {
58334
58514
  init_source();
@@ -75142,18 +75322,29 @@ var init_mcp_contracts = __esm(() => {
75142
75322
  exitCode: { type: "number", description: "Process exit code for local runs." },
75143
75323
  skill: stringSchema("Canonical skill slug."),
75144
75324
  remote: { type: "boolean", description: "Whether the skill was submitted to the hosted runtime." },
75145
- stdout: stringSchema("Captured stdout for local runs."),
75146
- stderr: stringSchema("Captured stderr for local runs."),
75325
+ stdoutPreview: objectSchema({
75326
+ text: stringSchema("Truncated stdout preview."),
75327
+ length: { type: "number" },
75328
+ truncated: { type: "boolean" }
75329
+ }, [], "Default compact stdout preview."),
75330
+ stderrPreview: objectSchema({
75331
+ text: stringSchema("Truncated stderr preview."),
75332
+ length: { type: "number" },
75333
+ truncated: { type: "boolean" }
75334
+ }, [], "Default compact stderr preview."),
75335
+ stdout: stringSchema("Captured stdout for local runs when detail:true is requested."),
75336
+ stderr: stringSchema("Captured stderr for local runs when detail:true is requested."),
75147
75337
  id: stringSchema("Remote run id when submitted remotely."),
75148
75338
  localRunId: stringSchema("Local run metadata id."),
75149
75339
  status: stringSchema("Run lifecycle status."),
75150
75340
  pricing: pricingSchema,
75151
- remoteRun: objectSchema({}, [], "Normalized hosted remote run contract.", true),
75152
- run: objectSchema({}, [], "Local run metadata.", true),
75341
+ remoteRun: objectSchema({}, [], "Compact hosted remote run summary by default; full contract when detail:true is requested.", true),
75342
+ run: objectSchema({}, [], "Compact local run metadata by default; full metadata when detail:true is requested.", true),
75153
75343
  nextActions: objectSchema({
75154
75344
  poll: stringSchema("Command to poll run status."),
75155
75345
  download: stringSchema("Command to download artifacts.")
75156
- })
75346
+ }),
75347
+ detailHint: stringSchema("How to request the complete payload.")
75157
75348
  }, [], "Skill run result.");
75158
75349
  toolContracts = [
75159
75350
  {
@@ -75201,7 +75392,7 @@ var init_mcp_contracts = __esm(() => {
75201
75392
  {
75202
75393
  name: "list_skills",
75203
75394
  title: "List Skills",
75204
- description: "List skills from the basic or full registry profile.",
75395
+ description: "List skills from the basic or full registry profile. Returns a compact paged envelope by default.",
75205
75396
  params: ["category?", "profile?", "detail?", "limit?", "offset?"],
75206
75397
  category: "discovery",
75207
75398
  sideEffects: "none",
@@ -75217,7 +75408,11 @@ var init_mcp_contracts = __esm(() => {
75217
75408
  skills: arraySchema(skillSummarySchema),
75218
75409
  total: { type: "number" },
75219
75410
  offset: { type: "number" },
75220
- limit: { type: "number" }
75411
+ limit: { type: "number" },
75412
+ nextOffset: { type: "number" },
75413
+ hasMore: { type: "boolean" },
75414
+ nextArguments: objectSchema({}, [], "Arguments for the next page.", true),
75415
+ detailHint: stringSchema("How to request fuller skill objects.")
75221
75416
  })
75222
75417
  },
75223
75418
  {
@@ -75238,7 +75433,7 @@ var init_mcp_contracts = __esm(() => {
75238
75433
  {
75239
75434
  name: "search_skills",
75240
75435
  title: "Search Skills",
75241
- description: "Search skills by name, description, or tags.",
75436
+ description: "Search skills by name, description, or tags. Returns a compact paged envelope by default.",
75242
75437
  params: ["query", "profile?", "detail?", "limit?", "offset?"],
75243
75438
  category: "discovery",
75244
75439
  sideEffects: "none",
@@ -75250,7 +75445,16 @@ var init_mcp_contracts = __esm(() => {
75250
75445
  limit: { type: "number", minimum: 0 },
75251
75446
  offset: { type: "number", minimum: 0 }
75252
75447
  }, ["query"]),
75253
- outputSchema: objectSchema({ skills: arraySchema(skillSummarySchema) })
75448
+ outputSchema: objectSchema({
75449
+ skills: arraySchema(skillSummarySchema),
75450
+ total: { type: "number" },
75451
+ offset: { type: "number" },
75452
+ limit: { type: "number" },
75453
+ nextOffset: { type: "number" },
75454
+ hasMore: { type: "boolean" },
75455
+ nextArguments: objectSchema({}, [], "Arguments for the next page.", true),
75456
+ detailHint: stringSchema("How to request fuller skill objects.")
75457
+ })
75254
75458
  },
75255
75459
  {
75256
75460
  name: "get_skill_info",
@@ -75367,8 +75571,8 @@ var init_mcp_contracts = __esm(() => {
75367
75571
  {
75368
75572
  name: "run_skill",
75369
75573
  title: "Run Skill",
75370
- description: "Run a skill locally or through a configured remote runner.",
75371
- params: ["name", "input?", "args?", "approved?"],
75574
+ description: "Run a skill locally or through a configured remote runner. Returns compact stdout/stderr previews and run summaries by default; pass detail:true for full records.",
75575
+ params: ["name", "input?", "args?", "approved?", "detail?"],
75372
75576
  category: "execution",
75373
75577
  sideEffects: "local-process-or-remote-run",
75374
75578
  stable: true,
@@ -75376,28 +75580,33 @@ var init_mcp_contracts = __esm(() => {
75376
75580
  name: skillNameInput,
75377
75581
  input: runInputSchema,
75378
75582
  args: runArgsSchema,
75379
- approved: paidRunApprovalSchema
75583
+ approved: paidRunApprovalSchema,
75584
+ detail: { type: "boolean", default: false, description: "Return full stdout/stderr, remote run, and local run metadata." }
75380
75585
  }, ["name"]),
75381
75586
  outputSchema: runOutputSchema
75382
75587
  },
75383
75588
  {
75384
75589
  name: "get_run_status",
75385
75590
  title: "Get Run Status",
75386
- description: "Fetch remote run status and next actions.",
75387
- params: ["run_id"],
75591
+ description: "Fetch remote run status and next actions. Returns a compact status summary by default; pass detail:true for the complete remote run payload.",
75592
+ params: ["run_id", "detail?"],
75388
75593
  category: "execution",
75389
75594
  sideEffects: "none",
75390
75595
  stable: true,
75391
- inputSchema: objectSchema({ run_id: stringSchema("Remote or local run id.") }, ["run_id"]),
75596
+ inputSchema: objectSchema({
75597
+ run_id: stringSchema("Remote or local run id."),
75598
+ detail: { type: "boolean", default: false, description: "Return the complete remote run payload." }
75599
+ }, ["run_id"]),
75392
75600
  outputSchema: objectSchema({
75393
75601
  contractVersion: { type: "number", description: "Remote run payload contract version." },
75394
75602
  runId: stringSchema("Remote run id."),
75395
75603
  localRunId: stringSchema("Local run id."),
75396
- run: objectSchema({}, [], "Normalized remote run status.", true),
75604
+ run: objectSchema({}, [], "Compact remote run status by default; full status when detail:true is requested.", true),
75397
75605
  nextActions: objectSchema({
75398
75606
  poll: stringSchema("Command to poll run status."),
75399
75607
  download: stringSchema("Command to download artifacts.")
75400
- })
75608
+ }),
75609
+ detailHint: stringSchema("How to request the complete payload.")
75401
75610
  })
75402
75611
  },
75403
75612
  {
@@ -75492,13 +75701,25 @@ var init_mcp_contracts = __esm(() => {
75492
75701
  {
75493
75702
  name: "list_schedules",
75494
75703
  title: "List Schedules",
75495
- description: "List scheduled skill runs.",
75496
- params: [],
75704
+ description: "List scheduled skill runs as a compact paged envelope.",
75705
+ params: ["limit?", "offset?"],
75497
75706
  category: "scheduling",
75498
75707
  sideEffects: "none",
75499
75708
  stable: true,
75500
- inputSchema: objectSchema(),
75501
- outputSchema: arraySchema(objectSchema({}, [], "Schedule record.", true))
75709
+ inputSchema: objectSchema({
75710
+ limit: { type: "number", minimum: 0 },
75711
+ offset: { type: "number", minimum: 0 }
75712
+ }),
75713
+ outputSchema: objectSchema({
75714
+ schedules: arraySchema(objectSchema({}, [], "Compact schedule record.", true)),
75715
+ total: { type: "number" },
75716
+ offset: { type: "number" },
75717
+ limit: { type: "number" },
75718
+ nextOffset: { type: "number" },
75719
+ hasMore: { type: "boolean" },
75720
+ nextArguments: objectSchema({}, [], "Arguments for the next page.", true),
75721
+ detailHint: stringSchema("How to request complete schedule details.")
75722
+ })
75502
75723
  },
75503
75724
  {
75504
75725
  name: "remove_schedule",
@@ -75710,7 +75931,7 @@ var init_helpers = __esm(() => {
75710
75931
  function registerDiscoveryTools(server) {
75711
75932
  server.registerTool("list_skills", {
75712
75933
  title: "List Skills",
75713
- description: "List skills with public pricing. Defaults to the clean basic profile to avoid context overflow. Set profile:'all' for the full registry. Returns {name,category,pricing} by default; detail:true for full public objects. Supports limit/offset pagination.",
75934
+ description: "List skills with public pricing. Defaults to a compact paged response from the basic profile to avoid context overflow. Set profile:'all' for the full registry, detail:true for full public objects, and use limit/offset to page.",
75714
75935
  inputSchema: {
75715
75936
  category: exports_external.string().optional(),
75716
75937
  profile: exports_external.enum(["basic", "all"]).optional(),
@@ -75722,16 +75943,20 @@ function registerDiscoveryTools(server) {
75722
75943
  const selectedProfile = profile || "basic";
75723
75944
  const skills = category ? loadRegistryProfile(selectedProfile).filter((s) => s.category === category) : loadRegistryProfile(selectedProfile);
75724
75945
  const mapped = detail ? skills.map(getPublicSkillDiscovery) : skills.map(getCompactSkillDiscovery);
75725
- if (limit !== undefined || offset !== undefined) {
75726
- const start = offset || 0;
75727
- const sliced = limit !== undefined ? mapped.slice(start, start + limit) : mapped.slice(start);
75728
- return {
75729
- content: [{ type: "text", text: JSON.stringify({ skills: sliced, total: mapped.length, offset: start, limit: limit ?? null }) }]
75730
- };
75731
- }
75732
- return {
75733
- content: [{ type: "text", text: JSON.stringify(mapped) }]
75734
- };
75946
+ const page = paginate(mapped, {
75947
+ limit: parsePageLimit(limit, DEFAULT_MCP_LIMIT, { max: 100 }),
75948
+ offset: parsePageOffset(offset)
75949
+ });
75950
+ return mcpJson({
75951
+ skills: page.items,
75952
+ total: page.total,
75953
+ offset: page.offset,
75954
+ limit: page.limit,
75955
+ nextOffset: page.nextOffset,
75956
+ hasMore: page.hasMore,
75957
+ nextArguments: page.hasMore ? { profile: selectedProfile, category, detail: Boolean(detail), limit: page.limit, offset: page.nextOffset } : null,
75958
+ detailHint: detail ? undefined : "Set detail:true for full public skill objects, or call get_skill_info for one skill."
75959
+ });
75735
75960
  });
75736
75961
  server.registerTool("list_pinned_skills", {
75737
75962
  title: "List Pinned Skills",
@@ -75748,7 +75973,7 @@ function registerDiscoveryTools(server) {
75748
75973
  });
75749
75974
  server.registerTool("search_skills", {
75750
75975
  title: "Search Skills",
75751
- description: "Search skills by name, description, or tags. Defaults to the clean basic profile; set profile:'all' for the full registry. Returns compact list with pricing by default. Supports limit/offset pagination.",
75976
+ description: "Search skills by name, description, or tags. Defaults to a compact paged response from the basic profile; set profile:'all' for the full registry and detail:true for full public objects.",
75752
75977
  inputSchema: {
75753
75978
  query: exports_external.string(),
75754
75979
  profile: exports_external.enum(["basic", "all"]).optional(),
@@ -75764,16 +75989,20 @@ function registerDiscoveryTools(server) {
75764
75989
  if (!cached2)
75765
75990
  cacheSet(cacheKey, results);
75766
75991
  const out = detail ? results.map(getPublicSkillDiscovery) : results.map(getCompactSkillDiscovery);
75767
- if (limit !== undefined || offset !== undefined) {
75768
- const start = offset || 0;
75769
- const sliced = limit !== undefined ? out.slice(start, start + limit) : out.slice(start);
75770
- return {
75771
- content: [{ type: "text", text: JSON.stringify({ skills: sliced, total: out.length, offset: start, limit: limit ?? null }) }]
75772
- };
75773
- }
75774
- return {
75775
- content: [{ type: "text", text: JSON.stringify(out) }]
75776
- };
75992
+ const page = paginate(out, {
75993
+ limit: parsePageLimit(limit, DEFAULT_MCP_LIMIT, { max: 100 }),
75994
+ offset: parsePageOffset(offset)
75995
+ });
75996
+ return mcpJson({
75997
+ skills: page.items,
75998
+ total: page.total,
75999
+ offset: page.offset,
76000
+ limit: page.limit,
76001
+ nextOffset: page.nextOffset,
76002
+ hasMore: page.hasMore,
76003
+ nextArguments: page.hasMore ? { query, profile: selectedProfile, detail: Boolean(detail), limit: page.limit, offset: page.nextOffset } : null,
76004
+ detailHint: detail ? undefined : "Set detail:true for full public skill objects, or call get_skill_info for one skill."
76005
+ });
75777
76006
  });
75778
76007
  server.registerTool("get_skill_info", {
75779
76008
  title: "Get Skill Info",
@@ -76146,9 +76375,10 @@ function registerOperationTools(server) {
76146
76375
  name: exports_external.string(),
76147
76376
  input: exports_external.record(exports_external.string(), exports_external.unknown()).optional(),
76148
76377
  args: exports_external.array(exports_external.string()).optional(),
76149
- approved: exports_external.boolean().optional()
76378
+ approved: exports_external.boolean().optional(),
76379
+ detail: exports_external.boolean().optional()
76150
76380
  }
76151
- }, async ({ name, input, args, approved }) => {
76381
+ }, async ({ name, input, args, approved, detail }) => {
76152
76382
  const skill = getSkill(name);
76153
76383
  if (!skill) {
76154
76384
  return mcpError("SKILL_NOT_FOUND", `Skill '${name}' not found`, findSimilarSkills(name));
@@ -76214,7 +76444,7 @@ function registerOperationTools(server) {
76214
76444
  });
76215
76445
  writeRunLogs(runContext, "", "");
76216
76446
  const remoteRunId = typeof run.id === "string" ? run.id : undefined;
76217
- return mcpJson({
76447
+ const payload2 = {
76218
76448
  contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
76219
76449
  id: run.id,
76220
76450
  localRunId: localRun2.id,
@@ -76225,7 +76455,8 @@ function registerOperationTools(server) {
76225
76455
  remoteRun: run,
76226
76456
  run: localRun2,
76227
76457
  nextActions: remoteRunNextActions(remoteRunId)
76228
- });
76458
+ };
76459
+ return mcpJson(detail ? payload2 : compactRunToolPayload(payload2, "Call run_skill again with detail:true for full remote/local run records."));
76229
76460
  } catch (err) {
76230
76461
  const error48 = `Hosted skill ${skillName} requires hosted access: ${err.message}`;
76231
76462
  writeRunLogs(runContext, "", error48 + `
@@ -76247,23 +76478,23 @@ function registerOperationTools(server) {
76247
76478
  status: result2.exitCode === 0 ? "completed" : "failed",
76248
76479
  error: result2.error
76249
76480
  });
76481
+ const payload = { exitCode: result2.exitCode, skill: skillName, stdout: result2.stdout, stderr: result2.stderr, run: localRun };
76250
76482
  if (result2.error) {
76251
76483
  return {
76252
- content: [{ type: "text", text: JSON.stringify({ exitCode: result2.exitCode, error: result2.error, run: localRun }, null, 2) }],
76484
+ content: [{ type: "text", text: JSON.stringify(detail ? { ...payload, error: result2.error } : compactRunToolPayload({ ...payload, error: result2.error }, "Call run_skill again with detail:true for full stdout/stderr and run metadata.")) }],
76253
76485
  isError: true
76254
76486
  };
76255
76487
  }
76256
- return {
76257
- content: [{ type: "text", text: JSON.stringify({ exitCode: result2.exitCode, skill: skillName, stdout: result2.stdout, stderr: result2.stderr, run: localRun }, null, 2) }]
76258
- };
76488
+ return mcpJson(detail ? payload : compactRunToolPayload(payload, "Call run_skill again with detail:true for full stdout/stderr and run metadata."));
76259
76489
  });
76260
76490
  server.registerTool("get_run_status", {
76261
76491
  title: "Get Run Status",
76262
76492
  description: "Fetch remote run status. Accepts a remote run id or a local run id linked to a remote run.",
76263
76493
  inputSchema: {
76264
- run_id: exports_external.string()
76494
+ run_id: exports_external.string(),
76495
+ detail: exports_external.boolean().optional()
76265
76496
  }
76266
- }, async ({ run_id }) => {
76497
+ }, async ({ run_id, detail }) => {
76267
76498
  const { getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_auth_store(), exports_auth_store));
76268
76499
  const apiKey = getApiKey2();
76269
76500
  if (!apiKey) {
@@ -76280,12 +76511,20 @@ function registerOperationTools(server) {
76280
76511
  const run = await client.getRun(remoteRunId);
76281
76512
  if (!run)
76282
76513
  return mcpError("RUN_NOT_FOUND", `Remote run '${remoteRunId}' not found`);
76283
- return mcpJson({
76514
+ const payload = {
76284
76515
  contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
76285
76516
  runId: remoteRunId,
76286
76517
  ...localRun ? { localRunId: localRun.id } : {},
76287
76518
  run,
76288
76519
  nextActions: remoteRunNextActions(remoteRunId)
76520
+ };
76521
+ return mcpJson(detail ? payload : {
76522
+ contractVersion: payload.contractVersion,
76523
+ runId: payload.runId,
76524
+ ...localRun ? { localRunId: localRun.id } : {},
76525
+ run: compactRemoteRun(run),
76526
+ nextActions: payload.nextActions,
76527
+ detailHint: "Call get_run_status with detail:true for the complete remote run payload."
76289
76528
  });
76290
76529
  } catch (err) {
76291
76530
  return mcpError("SKILLS_MD_ERROR", err.message);
@@ -76377,6 +76616,32 @@ function registerOperationTools(server) {
76377
76616
  return { content: [{ type: "text", text: JSON.stringify(result2, null, 2) }] };
76378
76617
  });
76379
76618
  }
76619
+ function compactRunToolPayload(payload, detailHint) {
76620
+ const stdout = previewText(payload.stdout ?? "");
76621
+ const stderr = previewText(payload.stderr ?? "");
76622
+ return {
76623
+ ...payload.contractVersion !== undefined ? { contractVersion: payload.contractVersion } : {},
76624
+ ...payload.id !== undefined ? { id: payload.id } : {},
76625
+ ...payload.localRunId !== undefined ? { localRunId: payload.localRunId } : {},
76626
+ ...payload.exitCode !== undefined ? { exitCode: payload.exitCode } : {},
76627
+ skill: payload.skill,
76628
+ ...payload.status !== undefined ? { status: payload.status } : {},
76629
+ ...payload.remote !== undefined ? { remote: payload.remote } : {},
76630
+ ...payload.correlationId !== undefined ? { correlationId: payload.correlationId } : {},
76631
+ ...payload.pricing !== undefined ? { pricing: payload.pricing } : {},
76632
+ ...payload.error !== undefined ? { error: payload.error } : {},
76633
+ ...payload.remoteRun !== undefined ? { remoteRun: compactRemoteRun(payload.remoteRun) } : {},
76634
+ run: compactRunRecord(payload.run),
76635
+ stdoutPreview: stdout,
76636
+ stderrPreview: stderr,
76637
+ stdoutChars: stdout.length,
76638
+ stderrChars: stderr.length,
76639
+ stdoutTruncated: stdout.truncated,
76640
+ stderrTruncated: stderr.truncated,
76641
+ ...payload.nextActions !== undefined ? { nextActions: payload.nextActions } : {},
76642
+ detailHint
76643
+ };
76644
+ }
76380
76645
  var init_operation_tools = __esm(() => {
76381
76646
  init_zod();
76382
76647
  init_package();
@@ -76785,11 +77050,37 @@ function registerScheduleTools(server) {
76785
77050
  });
76786
77051
  server.registerTool("list_schedules", {
76787
77052
  title: "List Schedules",
76788
- description: "List all scheduled skill runs.",
76789
- inputSchema: {}
76790
- }, async () => {
77053
+ description: "List scheduled skill runs as a compact paged response. Use limit/offset for pagination.",
77054
+ inputSchema: {
77055
+ limit: exports_external.number().optional(),
77056
+ offset: exports_external.number().optional()
77057
+ }
77058
+ }, async ({ limit, offset }) => {
76791
77059
  const schedules = listSchedules();
76792
- return { content: [{ type: "text", text: JSON.stringify(schedules, null, 2) }] };
77060
+ const page = paginate(schedules, {
77061
+ limit: parsePageLimit(limit, DEFAULT_MCP_LIMIT, { max: 100 }),
77062
+ offset: parsePageOffset(offset)
77063
+ });
77064
+ return mcpJson({
77065
+ schedules: page.items.map((schedule) => ({
77066
+ id: schedule.id,
77067
+ name: schedule.name,
77068
+ skill: schedule.skill,
77069
+ cron: schedule.cron,
77070
+ enabled: schedule.enabled,
77071
+ lastRun: schedule.lastRun,
77072
+ lastRunStatus: schedule.lastRunStatus,
77073
+ nextRun: schedule.nextRun,
77074
+ argCount: schedule.args?.length ?? 0
77075
+ })),
77076
+ total: page.total,
77077
+ offset: page.offset,
77078
+ limit: page.limit,
77079
+ nextOffset: page.nextOffset,
77080
+ hasMore: page.hasMore,
77081
+ nextArguments: page.hasMore ? { limit: page.limit, offset: page.nextOffset } : null,
77082
+ detailHint: "Use schedule state files or future schedule detail commands for complete schedule records."
77083
+ });
76793
77084
  });
76794
77085
  server.registerTool("remove_schedule", {
76795
77086
  title: "Remove Schedule",
@@ -76845,6 +77136,7 @@ var init_schedule_tools = __esm(() => {
76845
77136
  init_portable_skills();
76846
77137
  init_scheduler();
76847
77138
  init_skill_validation();
77139
+ init_helpers();
76848
77140
  });
76849
77141
 
76850
77142
  // src/lib/native-storage.ts
@@ -77627,7 +77919,7 @@ function registerRuntime(parent) {
77627
77919
  parent.command("quote").argument("<skill>", "Skill name").argument("[args...]", "Arguments that affect pricing, such as --count 8").allowUnknownOption(true).passThroughOptions(true).option("--json", "Output quote as JSON", false).description("Quote a skill run before spending account balance").action((name, args2, options) => handleQuote(name, args2, options));
77628
77920
  parent.command("run").argument("<skill>", "Skill name").argument("[args...]", "Arguments to pass to the skill").allowUnknownOption(true).passThroughOptions(true).option("--json", "Output result as JSON", false).option("-y, --yes", "Approve paid hosted execution without an interactive prompt", false).option("--wait", "Poll remote runs until a terminal status", false).option("--poll-interval-ms <ms>", "Remote polling interval in milliseconds", "1000").option("--poll-timeout-ms <ms>", "Maximum time to wait for a remote run", "300000").description("Run a skill directly").action(async (name, args2, options) => handleRun(name, args2, options));
77629
77921
  const runs = parent.command("runs").description("Inspect local skill run records");
77630
- runs.command("list").option("--json", "Output as JSON", false).option("--limit <n>", "Maximum number of runs", "20").description("List recent skill runs").action((options) => handleRunsList(options));
77922
+ runs.command("list").option("--json", "Output as JSON", false).option("--limit <n>", "Maximum number of runs", "20").option("--cursor <n>", "Numeric offset for human-output pagination", "0").description("List recent skill runs").action((options) => handleRunsList(options));
77631
77923
  runs.command("show").argument("<run-id>", "Run id").option("--json", "Output as JSON", false).description("Show a skill run record").action((runId, options) => handleRunsShow(runId, options));
77632
77924
  runs.command("status").argument("<run-id>", "Remote run id, or local run id linked to a remote run").option("--json", "Output as JSON", false).description("Fetch remote run status").action((runId, options) => handleRunsStatus(runId, options));
77633
77925
  const exportsCommand = parent.command("exports").description("Inspect or open skill run exports");
@@ -77986,22 +78278,32 @@ function writeBlogArticleValidationError(errors4, json2) {
77986
78278
  process.exitCode = 1;
77987
78279
  }
77988
78280
  function handleRunsList(options) {
77989
- const limit = Number.parseInt(options.limit, 10);
77990
- const runs = listSkillRuns(process.cwd(), Number.isFinite(limit) ? limit : 20);
77991
78281
  if (options.json) {
77992
- console.log(JSON.stringify(runs, null, 2));
78282
+ const jsonLimit = Number.parseInt(options.limit, 10);
78283
+ const runs2 = listSkillRuns(process.cwd(), Number.isFinite(jsonLimit) ? jsonLimit : 20);
78284
+ console.log(JSON.stringify(runs2, null, 2));
77993
78285
  return;
77994
78286
  }
78287
+ const limit = parsePageLimit(options.limit, DEFAULT_LIST_LIMIT, { allowAll: true });
78288
+ const offset = parsePageOffset(options.cursor);
78289
+ const fetchLimit = Number.isFinite(limit) ? limit + offset + 1 : Number.POSITIVE_INFINITY;
78290
+ const runs = listSkillRuns(process.cwd(), Number.isFinite(fetchLimit) ? fetchLimit : 1e4);
77995
78291
  if (!runs.length) {
77996
78292
  console.log(source_default.dim("No skill runs found"));
77997
78293
  return;
77998
78294
  }
78295
+ const hasMoreThanFetched = Number.isFinite(limit) && runs.length > offset + limit;
78296
+ const page = paginate(hasMoreThanFetched ? runs.slice(0, offset + limit) : runs, { limit, offset });
77999
78297
  console.log(source_default.bold(`
78000
- Recent skill runs (${runs.length}):
78298
+ Recent skill runs (${showingLabel(hasMoreThanFetched ? offset + limit + 1 : runs.length, page.items.length, page.offset)}):
78001
78299
  `));
78002
- for (const run of runs) {
78003
- console.log(` ${source_default.cyan(run.id)} ${run.skill} ${statusColor(run.status)} ${source_default.dim(run.startedAt)}`);
78300
+ for (const run of page.items) {
78301
+ console.log(` ${source_default.cyan(run.id)} ${run.skill} ${statusColor(run.status)} ${source_default.dim(run.startedAt)} artifacts:${run.artifacts.length}`);
78004
78302
  }
78303
+ if (hasMoreThanFetched)
78304
+ console.log(source_default.dim(`
78305
+ Next: skills runs list --cursor ${offset + page.items.length} --limit ${page.limit}`));
78306
+ console.log(source_default.dim("Details: skills runs show <run-id> or use --json for full run records."));
78005
78307
  }
78006
78308
  function handleRunsShow(runId, options) {
78007
78309
  const run = findSkillRun(runId);
@@ -78793,7 +79095,7 @@ function registerSchedule(parent) {
78793
79095
  console.log(source_default.dim(` Next run: ${new Date(schedule.nextRun).toLocaleString()}`));
78794
79096
  console.log(source_default.dim(` ID: ${schedule.id}`));
78795
79097
  });
78796
- scheduleCmd.command("list").option("--json", "Output as JSON", false).description("List all scheduled skills").action((options) => {
79098
+ scheduleCmd.command("list").option("--json", "Output as JSON", false).option("--limit <n>", "Maximum rows to print for human output (default: 30, use 0 or all for every row)").option("--cursor <n>", "Numeric offset for human-output pagination", "0").description("List all scheduled skills").action((options) => {
78797
79099
  const schedules = listSchedules();
78798
79100
  if (options.json) {
78799
79101
  console.log(JSON.stringify(schedules));
@@ -78803,15 +79105,25 @@ function registerSchedule(parent) {
78803
79105
  console.log(source_default.dim("No schedules. Run: skills schedule add <skill> <cron>"));
78804
79106
  return;
78805
79107
  }
79108
+ const page = paginate(schedules, {
79109
+ limit: parsePageLimit(options.limit, DEFAULT_LIST_LIMIT, { allowAll: true }),
79110
+ offset: parsePageOffset(options.cursor)
79111
+ });
78806
79112
  console.log(source_default.bold(`
78807
- Scheduled skills (${schedules.length}):
79113
+ Scheduled skills (${showingLabel(schedules.length, page.items.length, page.offset)}):
78808
79114
  `));
78809
- for (const s of schedules) {
79115
+ for (const s of page.items) {
78810
79116
  console.log(` ${source_default.cyan(s.name)} [${s.enabled ? source_default.green("enabled") : source_default.dim("disabled")}]`);
78811
79117
  const last2 = s.lastRun ? `last: ${new Date(s.lastRun).toLocaleString()} [${s.lastRunStatus ?? "?"}]` : "never run";
78812
79118
  const next = s.nextRun ? `next: ${new Date(s.nextRun).toLocaleString()}` : "";
78813
- console.log(source_default.dim(` skill: ${s.skill} cron: ${s.cron} ${last2} ${next}`));
79119
+ const args2 = s.args?.length ? ` args: ${truncateText(s.args.join(" "), 80)}` : "";
79120
+ console.log(source_default.dim(` ${s.id} skill: ${s.skill} cron: ${s.cron} ${last2} ${next}${args2}`));
78814
79121
  }
79122
+ if (page.hasMore && page.nextOffset !== null) {
79123
+ console.log(source_default.dim(`
79124
+ Next: skills schedule list --cursor ${page.nextOffset} --limit ${page.limit}`));
79125
+ }
79126
+ console.log(source_default.dim("Details: use --json for complete schedule records."));
78815
79127
  });
78816
79128
  scheduleCmd.command("remove").argument("<id-or-name>", "Schedule ID or name to remove").option("--json", "Output as JSON", false).description("Remove a schedule").action((idOrName, options) => {
78817
79129
  const removed = removeSchedule(idOrName);
@@ -85280,9 +85592,15 @@ function print(value, json, text) {
85280
85592
  else
85281
85593
  console.log(text);
85282
85594
  }
85595
+ function hasJsonOption(options) {
85596
+ return Boolean(options?.json || options?.opts?.().json || options?.optsWithGlobals?.().json || options?.parent?.opts?.().json || options?.parent?.optsWithGlobals?.().json);
85597
+ }
85598
+ function wantsJson(actionOptions, command) {
85599
+ return hasJsonOption(actionOptions) || hasJsonOption(command);
85600
+ }
85283
85601
  function registerWebhookCommands(program2, options) {
85284
85602
  const webhooks = program2.command(options.webhooksCommandName ?? "webhooks").description("Manage Hasna event webhook subscriptions");
85285
- webhooks.command("add").description("Add or replace a webhook or command subscription").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Subscription/channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions) => {
85603
+ webhooks.command("add").description("Add or replace a webhook or command subscription").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Subscription/channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions, command) => {
85286
85604
  const timestamp = new Date().toISOString();
85287
85605
  const channel = {
85288
85606
  id: actionOptions.id,
@@ -85303,11 +85621,11 @@ function registerWebhookCommands(program2, options) {
85303
85621
  throw new Error(`Transport ${actionOptions.transport} is reserved for future use and cannot be added yet`);
85304
85622
  }
85305
85623
  const saved = await createClient(options).addChannel(channel);
85306
- print(sanitizeChannelForOutput(saved), Boolean(actionOptions.json), `Added ${saved.transport} channel ${saved.id}`);
85624
+ print(sanitizeChannelForOutput(saved), wantsJson(actionOptions, command), `Added ${saved.transport} channel ${saved.id}`);
85307
85625
  });
85308
- webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
85626
+ webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
85309
85627
  const channels = await createClient(options).listChannels();
85310
- if (actionOptions.json) {
85628
+ if (wantsJson(actionOptions, command)) {
85311
85629
  console.log(JSON.stringify(sanitizeChannelsForOutput(channels), null, 2));
85312
85630
  return;
85313
85631
  }
@@ -85319,11 +85637,11 @@ function registerWebhookCommands(program2, options) {
85319
85637
  console.log(`${channel.id} ${channel.enabled ? "enabled" : "disabled"} ${channel.transport} ${channel.webhook?.url ?? channel.command?.command ?? channel.transport}`);
85320
85638
  }
85321
85639
  });
85322
- webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions) => {
85640
+ webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
85323
85641
  const removed = await createClient(options).removeChannel(id);
85324
- print({ removed }, Boolean(actionOptions.json), removed ? `Removed ${id}` : `Channel not found: ${id}`);
85642
+ print({ removed }, wantsJson(actionOptions, command), removed ? `Removed ${id}` : `Channel not found: ${id}`);
85325
85643
  });
85326
- webhooks.command("test").description("Send a test event to one subscription").argument("<id>", "Subscription/channel identifier").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions) => {
85644
+ webhooks.command("test").description("Send a test event to one subscription").argument("<id>", "Subscription/channel identifier").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
85327
85645
  const result2 = await createClient(options).testChannel(id, {
85328
85646
  source: options.source,
85329
85647
  type: actionOptions.type,
@@ -85331,13 +85649,13 @@ function registerWebhookCommands(program2, options) {
85331
85649
  message: actionOptions.message,
85332
85650
  data: parseJsonObject(actionOptions.data, { test: true })
85333
85651
  });
85334
- print(result2, Boolean(actionOptions.json), `${result2.status}: ${result2.channelId}`);
85652
+ print(result2, wantsJson(actionOptions, command), `${result2.status}: ${result2.channelId}`);
85335
85653
  });
85336
85654
  return webhooks;
85337
85655
  }
85338
85656
  function registerEventCommands(program2, options) {
85339
85657
  const events = program2.command(options.eventsCommandName ?? "events").description("Emit, list, and replay Hasna events");
85340
- events.command("emit").description("Emit an event from this app").argument("<type>", "Event type").option("--source <source>", "Event source override").option("--subject <subject>", "Event subject").option("--severity <severity>", "Event severity", "info").option("--message <message>", "Event message").option("--dedupe-key <key>", "Dedupe key").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--no-deliver", "Record without delivering").option("--no-dedupe", "Allow duplicate id/dedupeKey events").option("-j, --json", "Print JSON output", false).action(async (type, actionOptions) => {
85658
+ events.command("emit").description("Emit an event from this app").argument("<type>", "Event type").option("--source <source>", "Event source override").option("--subject <subject>", "Event subject").option("--severity <severity>", "Event severity", "info").option("--message <message>", "Event message").option("--dedupe-key <key>", "Dedupe key").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--no-deliver", "Record without delivering").option("--no-dedupe", "Allow duplicate id/dedupeKey events").option("-j, --json", "Print JSON output", false).action(async (type, actionOptions, command) => {
85341
85659
  const result2 = await createClient(options).emit({
85342
85660
  source: actionOptions.source ?? options.source,
85343
85661
  type,
@@ -85348,9 +85666,9 @@ function registerEventCommands(program2, options) {
85348
85666
  data: parseJsonObject(actionOptions.data, {}),
85349
85667
  metadata: parseJsonObject(actionOptions.metadata, {})
85350
85668
  }, { deliver: actionOptions.deliver, dedupe: actionOptions.dedupe });
85351
- print(result2, Boolean(actionOptions.json), `${result2.deduped ? "Deduped" : "Emitted"} ${result2.event.id} to ${result2.deliveries.length} channel(s)`);
85669
+ print(result2, wantsJson(actionOptions, command), `${result2.deduped ? "Deduped" : "Emitted"} ${result2.event.id} to ${result2.deliveries.length} channel(s)`);
85352
85670
  });
85353
- events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", "Limit results", parseNumber).option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
85671
+ events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", "Limit results", parseNumber).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
85354
85672
  let rows = await createClient(options).listEvents();
85355
85673
  if (actionOptions.source)
85356
85674
  rows = rows.filter((event) => event.source === actionOptions.source);
@@ -85358,7 +85676,7 @@ function registerEventCommands(program2, options) {
85358
85676
  rows = rows.filter((event) => event.type === actionOptions.type);
85359
85677
  if (actionOptions.limit)
85360
85678
  rows = rows.slice(-actionOptions.limit);
85361
- if (actionOptions.json) {
85679
+ if (wantsJson(actionOptions, command)) {
85362
85680
  console.log(JSON.stringify(rows, null, 2));
85363
85681
  return;
85364
85682
  }
@@ -85369,14 +85687,14 @@ function registerEventCommands(program2, options) {
85369
85687
  for (const event of rows)
85370
85688
  console.log(`${event.time} ${event.id} ${event.source} ${event.type} ${event.severity}`);
85371
85689
  });
85372
- events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
85690
+ events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
85373
85691
  const result2 = await createClient(options).replay({
85374
85692
  eventId: actionOptions.id,
85375
85693
  source: actionOptions.source,
85376
85694
  type: actionOptions.type,
85377
85695
  dryRun: actionOptions.dryRun
85378
85696
  });
85379
- print(result2, Boolean(actionOptions.json), `Replayed ${result2.events.length} event(s), ${result2.deliveries.length} delivery result(s)`);
85697
+ print(result2, wantsJson(actionOptions, command), `Replayed ${result2.events.length} event(s), ${result2.deliveries.length} delivery result(s)`);
85380
85698
  });
85381
85699
  return events;
85382
85700
  }