@hasna/skills 0.1.46 → 0.1.48

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.46",
36863
+ version: "0.1.48",
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",
@@ -37848,7 +37848,7 @@ var require_jsx_dev_runtime = __commonJS((exports, module) => {
37848
37848
  });
37849
37849
 
37850
37850
  // src/lib/config.ts
37851
- import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync, mkdirSync, copyFileSync } from "fs";
37851
+ import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync, mkdirSync, copyFileSync, readdirSync, statSync } from "fs";
37852
37852
  import { join as join3, dirname } from "path";
37853
37853
  import { homedir as homedir2 } from "os";
37854
37854
  function validKeys() {
@@ -37859,6 +37859,24 @@ function allowedValues(key) {
37859
37859
  return MODE_VALUES;
37860
37860
  return ENUM_KEYS[key];
37861
37861
  }
37862
+ function mergeDirectoryContents(sourceDir, targetDir) {
37863
+ if (!existsSync3(sourceDir))
37864
+ return;
37865
+ mkdirSync(targetDir, { recursive: true });
37866
+ for (const entry of readdirSync(sourceDir)) {
37867
+ const sourcePath = join3(sourceDir, entry);
37868
+ const targetPath = join3(targetDir, entry);
37869
+ try {
37870
+ const sourceStat = statSync(sourcePath);
37871
+ if (sourceStat.isDirectory()) {
37872
+ mergeDirectoryContents(sourcePath, targetPath);
37873
+ continue;
37874
+ }
37875
+ if (!existsSync3(targetPath))
37876
+ copyFileSync(sourcePath, targetPath);
37877
+ } catch {}
37878
+ }
37879
+ }
37862
37880
  function normalizeConfigValue(key, value) {
37863
37881
  if (typeof value !== "string")
37864
37882
  return;
@@ -37882,14 +37900,17 @@ function normalizeConfigValue(key, value) {
37882
37900
  function getDataDir() {
37883
37901
  const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir2();
37884
37902
  const newDir = join3(home, ".hasna", "skills");
37903
+ const oldDir = join3(home, ".skills");
37885
37904
  const oldConfigFile = join3(home, ".skillsrc");
37905
+ mkdirSync(newDir, { recursive: true });
37906
+ try {
37907
+ mergeDirectoryContents(oldDir, newDir);
37908
+ } catch {}
37886
37909
  if (existsSync3(oldConfigFile) && !existsSync3(join3(newDir, "config.json"))) {
37887
- mkdirSync(newDir, { recursive: true });
37888
37910
  try {
37889
37911
  copyFileSync(oldConfigFile, join3(newDir, "config.json"));
37890
37912
  } catch {}
37891
37913
  }
37892
- mkdirSync(newDir, { recursive: true });
37893
37914
  return newDir;
37894
37915
  }
37895
37916
  function getConfigPath(scope) {
@@ -37993,7 +38014,8 @@ var init_skill_aliases = __esm(() => {
37993
38014
  "pdf-reader": "read-pdf",
37994
38015
  "generate-image": "image",
37995
38016
  "image-generator": "image",
37996
- "create-blog-article": "blog-article"
38017
+ "create-blog-article": "blog-article",
38018
+ "skill-diff": "diff-viewer"
37997
38019
  };
37998
38020
  });
37999
38021
 
@@ -38410,7 +38432,7 @@ var init_pricing = __esm(() => {
38410
38432
  { 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
38433
  { 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
38434
  { 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" },
38435
+ { slug: "transcript", displayName: "Transcript", tier: "premium", costCents: 10, providers: ["openai", "elevenlabs", "deepgram", "hosted"], description: "Audio/video transcription with timestamps, diarization, and URL support" },
38414
38436
  { slug: "webcrawling", displayName: "Web Crawling", tier: "premium", costCents: 5, providers: ["firecrawl"], description: "Structured web page crawling and extraction" },
38415
38437
  { slug: "browse", displayName: "Browse", tier: "premium", costCents: 5, providers: ["browser"], description: "Web browsing and page interaction" },
38416
38438
  { slug: "read-pdf", displayName: "Read PDF", tier: "premium", costCents: 5, providers: ["cerebras"], description: "Hosted PDF extraction and structured content analysis" },
@@ -38477,7 +38499,7 @@ var init_pricing = __esm(() => {
38477
38499
  });
38478
38500
 
38479
38501
  // src/lib/skill-validation.ts
38480
- import { existsSync as existsSync4, lstatSync, readFileSync as readFileSync3, readdirSync, statSync } from "fs";
38502
+ import { existsSync as existsSync4, lstatSync, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
38481
38503
  import { isAbsolute, join as join4, normalize } from "path";
38482
38504
  function add2(target, code, message) {
38483
38505
  target.push({ code, message });
@@ -38585,7 +38607,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
38585
38607
  if (!VALID_BIN_COMMAND.test(bareName)) {
38586
38608
  add2(issues, "skill.name_invalid", `Skill name '${bareName}' must use lowercase letters, numbers, dots, underscores, or hyphens`);
38587
38609
  }
38588
- for (const entry of readdirSync(skillPath).sort()) {
38610
+ for (const entry of readdirSync2(skillPath).sort()) {
38589
38611
  const entryPath = join4(skillPath, entry);
38590
38612
  if (RESERVED_SKILL_ENTRIES.has(entry)) {
38591
38613
  add2(issues, "skill.reserved_file", `Reserved file '${entry}' is not allowed in skill packages`);
@@ -38700,7 +38722,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
38700
38722
  const targetPath = join4(skillPath, target);
38701
38723
  if (!existsSync4(targetPath)) {
38702
38724
  add2(warnings, "package.bin_target_missing", `package.json bin '${command}' target '${target}' is not present before build`);
38703
- } else if (statSync(targetPath).isDirectory()) {
38725
+ } else if (statSync2(targetPath).isDirectory()) {
38704
38726
  add2(issues, "package.bin_target_directory", `package.json bin '${command}' target '${target}' must point to a file, not a directory`);
38705
38727
  }
38706
38728
  }
@@ -38723,7 +38745,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
38723
38745
  add2(issues, "skill.src_index_missing", "Missing src/index.ts or src/index.js");
38724
38746
  } else {
38725
38747
  const indexPath = existsSync4(join4(srcDir, "index.ts")) ? join4(srcDir, "index.ts") : join4(srcDir, "index.js");
38726
- const size2 = statSync(indexPath).size;
38748
+ const size2 = statSync2(indexPath).size;
38727
38749
  if (size2 < 50)
38728
38750
  add2(warnings, "skill.src_index_minimal", `Source entry point is very small (${size2}B)`);
38729
38751
  }
@@ -38796,9 +38818,9 @@ import {
38796
38818
  lstatSync as lstatSync2,
38797
38819
  mkdirSync as mkdirSync2,
38798
38820
  readFileSync as readFileSync4,
38799
- readdirSync as readdirSync2,
38821
+ readdirSync as readdirSync3,
38800
38822
  rmSync,
38801
- statSync as statSync2,
38823
+ statSync as statSync3,
38802
38824
  writeFileSync as writeFileSync2
38803
38825
  } from "fs";
38804
38826
  import { basename, dirname as dirname2, isAbsolute as isAbsolute2, join as join5, normalize as normalize2, relative } from "path";
@@ -38829,7 +38851,7 @@ function findPortableSkill(name, options = {}) {
38829
38851
  return null;
38830
38852
  }
38831
38853
  const path = getPortableSkillPath(normalized, options);
38832
- if (!existsSync5(path) || !statSync2(path).isDirectory())
38854
+ if (!existsSync5(path) || !statSync3(path).isDirectory())
38833
38855
  return null;
38834
38856
  try {
38835
38857
  return summarizePortableSkill(path, normalized);
@@ -38842,7 +38864,7 @@ function listPortableSkills(options = {}) {
38842
38864
  if (!existsSync5(root))
38843
38865
  return [];
38844
38866
  const skills = [];
38845
- for (const entry of readdirSync2(root).sort()) {
38867
+ for (const entry of readdirSync3(root).sort()) {
38846
38868
  if (entry.startsWith(".") || DATA_DIR_NON_SKILL_ENTRIES.has(entry))
38847
38869
  continue;
38848
38870
  const path = join5(root, entry);
@@ -38918,7 +38940,7 @@ function scaffoldPortableSkill(name, options = {}) {
38918
38940
  }
38919
38941
  function portPortableSkill(sourcePath, options = {}) {
38920
38942
  const absoluteSource = normalize2(sourcePath);
38921
- if (!existsSync5(absoluteSource) || !statSync2(absoluteSource).isDirectory()) {
38943
+ if (!existsSync5(absoluteSource) || !statSync3(absoluteSource).isDirectory()) {
38922
38944
  throw new Error(`Skill source directory not found: ${sourcePath}`);
38923
38945
  }
38924
38946
  const inferred = readPortableSkillManifest(absoluteSource, basename(absoluteSource));
@@ -38987,7 +39009,7 @@ function validatePortableSkillDirectory(name, skillPath) {
38987
39009
  const entryPath = join5(skillPath, command.entry);
38988
39010
  if (!existsSync5(entryPath))
38989
39011
  add3(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
38990
- else if (statSync2(entryPath).isDirectory())
39012
+ else if (statSync3(entryPath).isDirectory())
38991
39013
  add3(issues, "portable.command_entry_directory", `Command '${command.name}' entry '${command.entry}' must be a file`);
38992
39014
  }
38993
39015
  }
@@ -39355,7 +39377,7 @@ function displayName(name) {
39355
39377
  }
39356
39378
  function safeIsDirectory(path) {
39357
39379
  try {
39358
- return statSync2(path).isDirectory();
39380
+ return statSync3(path).isDirectory();
39359
39381
  } catch {
39360
39382
  return false;
39361
39383
  }
@@ -40616,9 +40638,9 @@ var init_media_processing = __esm(() => {
40616
40638
  {
40617
40639
  name: "transcript",
40618
40640
  displayName: "Transcript",
40619
- description: "Generate transcripts from audio and video files with timestamps",
40641
+ description: "Transcribe audio, video, and media URLs with OpenAI GPT-4o, ElevenLabs Scribe v2, DeepGram, or hosted runtime",
40620
40642
  category: "Media Processing",
40621
- tags: ["transcript", "audio", "video", "speech-to-text"]
40643
+ tags: ["transcript", "audio", "video", "speech-to-text", "diarization", "youtube"]
40622
40644
  },
40623
40645
  {
40624
40646
  name: "video-cut-suggester",
@@ -41437,7 +41459,7 @@ __export(exports_registry, {
41437
41459
  CATEGORIES: () => CATEGORIES,
41438
41460
  BASIC_SKILL_NAMES: () => BASIC_SKILL_NAMES
41439
41461
  });
41440
- import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync3 } from "fs";
41462
+ import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync4 } from "fs";
41441
41463
  import { join as join6 } from "path";
41442
41464
  function isBasicSkillName(name) {
41443
41465
  return BASIC_SKILL_NAMES.includes(name);
@@ -41475,7 +41497,7 @@ function discoverSkillsInDir(dir) {
41475
41497
  return [];
41476
41498
  const result2 = [];
41477
41499
  try {
41478
- const entries = readdirSync3(dir, { withFileTypes: true });
41500
+ const entries = readdirSync4(dir, { withFileTypes: true });
41479
41501
  for (const entry of entries) {
41480
41502
  if (!entry.isDirectory())
41481
41503
  continue;
@@ -54491,7 +54513,7 @@ function finalize(ctx, schema) {
54491
54513
  result2.$schema = "http://json-schema.org/draft-07/schema#";
54492
54514
  } else if (ctx.target === "draft-04") {
54493
54515
  result2.$schema = "http://json-schema.org/draft-04/schema#";
54494
- } else if (ctx.target === "openapi-3.0") {}
54516
+ } else if (ctx.target === "openapi-3.0") {} else {}
54495
54517
  if (ctx.external?.uri) {
54496
54518
  const id = ctx.external.registry.get(schema)?.id;
54497
54519
  if (!id)
@@ -54756,7 +54778,7 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
54756
54778
  if (val === undefined) {
54757
54779
  if (ctx.unrepresentable === "throw") {
54758
54780
  throw new Error("Literal `undefined` cannot be represented in JSON Schema");
54759
- }
54781
+ } else {}
54760
54782
  } else if (typeof val === "bigint") {
54761
54783
  if (ctx.unrepresentable === "throw") {
54762
54784
  throw new Error("BigInt literals cannot be represented in JSON Schema");
@@ -58086,30 +58108,119 @@ var init_install = __esm(() => {
58086
58108
  init_installer();
58087
58109
  });
58088
58110
 
58111
+ // src/lib/compact-output.ts
58112
+ function truncateText(value, maxChars = 96) {
58113
+ const text = String(value ?? "").replace(/\s+/g, " ").trim();
58114
+ if (text.length <= maxChars)
58115
+ return text;
58116
+ return `${text.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
58117
+ }
58118
+ function previewText(value, maxChars = DEFAULT_PREVIEW_CHARS) {
58119
+ const text = String(value ?? "");
58120
+ return {
58121
+ text: text.length > maxChars ? `${text.slice(0, Math.max(0, maxChars - 3))}...` : text,
58122
+ length: text.length,
58123
+ truncated: text.length > maxChars
58124
+ };
58125
+ }
58126
+ function parsePageLimit(value, fallback, options = {}) {
58127
+ const max2 = options.max ?? MAX_PAGE_LIMIT;
58128
+ if (typeof value === "string" && options.allowAll && value.trim().toLowerCase() === "all") {
58129
+ return Number.POSITIVE_INFINITY;
58130
+ }
58131
+ const parsed = typeof value === "number" ? value : Number.parseInt(value ?? "", 10);
58132
+ if (!Number.isFinite(parsed))
58133
+ return fallback;
58134
+ if (options.allowAll && parsed === 0)
58135
+ return Number.POSITIVE_INFINITY;
58136
+ if (parsed <= 0)
58137
+ return fallback;
58138
+ return Math.min(parsed, max2);
58139
+ }
58140
+ function parsePageOffset(value, fallback = 0) {
58141
+ const parsed = typeof value === "number" ? value : Number.parseInt(value ?? "", 10);
58142
+ if (!Number.isFinite(parsed) || parsed < 0)
58143
+ return fallback;
58144
+ return parsed;
58145
+ }
58146
+ function paginate(items, options) {
58147
+ const offset = Math.min(parsePageOffset(options.offset), items.length);
58148
+ const effectiveLimit = Number.isFinite(options.limit) ? Math.max(0, Math.min(options.limit, MAX_PAGE_LIMIT)) : Math.max(0, items.length - offset);
58149
+ const pageItems = items.slice(offset, offset + effectiveLimit);
58150
+ const nextOffset = offset + pageItems.length < items.length ? offset + pageItems.length : null;
58151
+ return {
58152
+ items: pageItems,
58153
+ total: items.length,
58154
+ offset,
58155
+ limit: effectiveLimit,
58156
+ hasMore: nextOffset !== null,
58157
+ nextOffset
58158
+ };
58159
+ }
58160
+ function showingLabel(total, shown, offset) {
58161
+ if (offset > 0 || shown < total)
58162
+ return `showing ${shown} of ${total}, cursor ${offset}`;
58163
+ return String(total);
58164
+ }
58165
+ function compactRunRecord(run) {
58166
+ if (!run || typeof run !== "object")
58167
+ return {};
58168
+ return {
58169
+ id: run.id,
58170
+ skill: run.skill,
58171
+ status: run.status,
58172
+ startedAt: run.startedAt,
58173
+ ...run.completedAt ? { completedAt: run.completedAt } : {},
58174
+ ...run.remoteRunId ? { remoteRunId: run.remoteRunId } : {},
58175
+ ...run.costCents !== undefined ? { costCents: run.costCents } : {},
58176
+ ...run.error ? { error: truncateText(run.error, 240) } : {},
58177
+ artifactCount: Array.isArray(run.artifacts) ? run.artifacts.length : 0,
58178
+ paths: run.paths
58179
+ };
58180
+ }
58181
+ function compactRemoteRun(run) {
58182
+ if (!run || typeof run !== "object")
58183
+ return {};
58184
+ return {
58185
+ ...run.contractVersion !== undefined ? { contractVersion: run.contractVersion } : {},
58186
+ id: run.id,
58187
+ skill: run.skill ?? run.requestedSlug,
58188
+ status: run.status,
58189
+ ...run.correlationId ? { correlationId: run.correlationId } : {},
58190
+ ...run.createdAt ? { createdAt: run.createdAt } : {},
58191
+ ...run.startedAt ? { startedAt: run.startedAt } : {},
58192
+ ...run.completedAt ? { completedAt: run.completedAt } : {},
58193
+ ...run.error || run.errorMessage ? { error: truncateText(run.error ?? run.errorMessage, 240) } : {}
58194
+ };
58195
+ }
58196
+ 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;
58197
+
58089
58198
  // src/cli/commands/list.ts
58090
58199
  var exports_list = {};
58091
58200
  __export(exports_list, {
58092
58201
  registerBrowse: () => registerBrowse
58093
58202
  });
58094
58203
  function registerBrowse(parent) {
58095
- 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) => {
58204
+ 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) => {
58096
58205
  return handleList(options).catch(handleBrowseError);
58097
58206
  });
58098
- 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) => {
58207
+ 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) => {
58099
58208
  return handleSearch(query, options).catch(handleBrowseError);
58100
58209
  });
58101
58210
  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) => {
58102
58211
  return handleCategories(options).catch(handleBrowseError);
58103
58212
  });
58104
- 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) => {
58213
+ 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) => {
58105
58214
  return handleTags(options).catch(handleBrowseError);
58106
58215
  });
58107
58216
  }
58108
58217
  function formatBrief(skill) {
58109
- return `${skill.name} \u2014 ${skill.description} (${publicDiscoveryPriceLabel(skill)}) [${skill.category}]`;
58218
+ return `${skill.name} \u2014 ${truncateText(skill.description, 110)} (${publicDiscoveryPriceLabel(skill)}) [${skill.category}]`;
58110
58219
  }
58111
- function formatSkillLine(skill) {
58112
- return ` ${source_default.cyan(skill.name)}${skill.source === "custom" ? source_default.yellow(" [custom]") : ""} ${source_default.dim(`(${publicDiscoveryPriceLabel(skill)})`)} - ${skill.description}`;
58220
+ function formatSkillLine(skill, options = {}) {
58221
+ const description = truncateText(skill.description, options.verbose ? 180 : 88);
58222
+ const tags = options.verbose && skill.tags.length ? source_default.dim(` tags: ${skill.tags.join(", ")}`) : "";
58223
+ 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}`;
58113
58224
  }
58114
58225
  function enrichDiscovery(skills) {
58115
58226
  return skills.map(getPublicSkillDiscovery);
@@ -58149,6 +58260,8 @@ async function handleList(options) {
58149
58260
  const fmt = !options.json ? options.format : undefined;
58150
58261
  const profile = options.all ? "all" : "basic";
58151
58262
  const registry2 = await getBrowseRegistry(options);
58263
+ const limit = parsePageLimit(options.limit, DEFAULT_LIST_LIMIT, { allowAll: true });
58264
+ const offset = parsePageOffset(options.cursor);
58152
58265
  if (options.pinned) {
58153
58266
  const installed = getInstalledSkills();
58154
58267
  if (options.json) {
@@ -58172,14 +58285,16 @@ async function handleList(options) {
58172
58285
  }
58173
58286
  const meta3 = getInstallMeta();
58174
58287
  const registry3 = loadRegistry();
58288
+ const page2 = paginate(installed, { limit, offset });
58175
58289
  console.log(source_default.bold(`
58176
- Pinned skills (${installed.length}):
58290
+ Pinned skills (${showingLabel(installed.length, page2.items.length, page2.offset)}):
58177
58291
  `));
58178
- for (const name of installed) {
58292
+ for (const name of page2.items) {
58179
58293
  const m = meta3.skills[name];
58180
58294
  const s = registry3.find((r) => r.name === name);
58181
58295
  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()) : ""}`);
58182
58296
  }
58297
+ printPageHint(page2, "skills list --pinned");
58183
58298
  return;
58184
58299
  }
58185
58300
  const tagFilter = options.tags ? options.tags.split(",").map((t) => t.trim().toLowerCase()).filter(Boolean) : null;
@@ -58200,16 +58315,19 @@ Available: ${categories.join(", ")}`);
58200
58315
  await writeJson(output, 2);
58201
58316
  return;
58202
58317
  }
58318
+ const page2 = paginate(output, { limit, offset });
58203
58319
  if (brief) {
58204
- for (const s of output)
58320
+ for (const s of page2.items)
58205
58321
  console.log(formatBrief(s));
58322
+ printPageHint(page2, listCommand(options));
58206
58323
  return;
58207
58324
  }
58208
58325
  console.log(source_default.bold(`
58209
- ${category} (${skills.length}):
58326
+ ${category} (${showingLabel(output.length, page2.items.length, page2.offset)}):
58210
58327
  `));
58211
- for (const s of output)
58212
- console.log(formatSkillLine(s));
58328
+ for (const s of page2.items)
58329
+ console.log(formatSkillLine(s, { verbose: options.verbose }));
58330
+ printSkillHint(page2, listCommand(options));
58213
58331
  return;
58214
58332
  }
58215
58333
  if (tagFilter) {
@@ -58219,16 +58337,19 @@ ${category} (${skills.length}):
58219
58337
  await writeJson(output, 2);
58220
58338
  return;
58221
58339
  }
58340
+ const page2 = paginate(output, { limit, offset });
58222
58341
  if (brief) {
58223
- for (const s of output)
58342
+ for (const s of page2.items)
58224
58343
  console.log(formatBrief(s));
58344
+ printPageHint(page2, listCommand(options));
58225
58345
  return;
58226
58346
  }
58227
58347
  console.log(source_default.bold(`
58228
- Skills matching tags [${tagFilter.join(", ")}] (${skills.length}):
58348
+ Skills matching tags [${tagFilter.join(", ")}] (${showingLabel(output.length, page2.items.length, page2.offset)}):
58229
58349
  `));
58230
- for (const s of output)
58231
- 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}`);
58350
+ for (const s of page2.items)
58351
+ console.log(formatSkillLine(s, { verbose: options.verbose }));
58352
+ printSkillHint(page2, listCommand(options));
58232
58353
  return;
58233
58354
  }
58234
58355
  const allSkills = enrichDiscovery(registry2);
@@ -58250,28 +58371,21 @@ Skills matching tags [${tagFilter.join(", ")}] (${skills.length}):
58250
58371
  return;
58251
58372
  }
58252
58373
  if (brief) {
58253
- for (const s of [...allSkills].sort((a, b) => a.category.localeCompare(b.category) || a.name.localeCompare(b.name)))
58374
+ const sorted2 = [...allSkills].sort((a, b) => a.category.localeCompare(b.category) || a.name.localeCompare(b.name));
58375
+ const page2 = paginate(sorted2, { limit, offset });
58376
+ for (const s of page2.items)
58254
58377
  console.log(formatBrief(s));
58378
+ printPageHint(page2, listCommand(options));
58255
58379
  return;
58256
58380
  }
58381
+ const sorted = [...allSkills].sort((a, b) => a.category.localeCompare(b.category) || a.name.localeCompare(b.name));
58382
+ const page = paginate(sorted, { limit, offset });
58257
58383
  console.log(source_default.bold(`
58258
- Available ${profile === "basic" ? "default " : ""}skills (${allSkills.length}):
58384
+ Available ${profile === "basic" ? "default " : ""}skills (${showingLabel(allSkills.length, page.items.length, page.offset)}):
58259
58385
  `));
58260
- for (const category of registryCategories(allSkills)) {
58261
- const skills = allSkills.filter((s) => s.category === category);
58262
- if (skills.length === 0)
58263
- continue;
58264
- console.log(source_default.bold(`${category} (${skills.length}):`));
58265
- for (const s of skills)
58266
- console.log(formatSkillLine(s));
58267
- console.log();
58268
- }
58269
- const customUncategorized = allSkills.filter((s) => s.source === "custom" && !CATEGORIES.includes(s.category));
58270
- if (customUncategorized.length > 0) {
58271
- console.log(source_default.bold(`Custom (${customUncategorized.length}):`));
58272
- for (const s of customUncategorized)
58273
- console.log(` ${source_default.yellow(s.name)} ${source_default.dim(`(${publicDiscoveryPriceLabel(s)})`)} - ${s.description}`);
58274
- }
58386
+ for (const s of page.items)
58387
+ console.log(formatSkillLine(s, { verbose: options.verbose }));
58388
+ printSkillHint(page, listCommand(options));
58275
58389
  }
58276
58390
  async function handleSearch(query, options) {
58277
58391
  const registry2 = await getBrowseRegistry(options);
@@ -58318,19 +58432,22 @@ Available: ${categories.join(", ")}`);
58318
58432
  }
58319
58433
  return;
58320
58434
  }
58435
+ const limit = parsePageLimit(options.limit, DEFAULT_SEARCH_LIMIT, { allowAll: true });
58436
+ const offset = parsePageOffset(options.cursor);
58437
+ const page = paginate(output, { limit, offset });
58321
58438
  if (brief) {
58322
- for (const s of output)
58439
+ for (const s of page.items)
58323
58440
  console.log(formatBrief(s));
58441
+ printPageHint(page, searchCommand(query, options));
58324
58442
  return;
58325
58443
  }
58326
58444
  console.log(source_default.bold(`
58327
- Found ${output.length} skill(s):
58445
+ Found ${skillCountLabel(output.length, page.items.length, page.offset)} for "${query}":
58328
58446
  `));
58329
- for (const s of output) {
58330
- console.log(` ${source_default.cyan(s.name)} ${source_default.dim(`[${s.category}]`)}`);
58331
- console.log(` ${source_default.dim("Price:")} ${publicDiscoveryPriceLabel(s)}`);
58332
- console.log(` ${s.description}`);
58447
+ for (const s of page.items) {
58448
+ console.log(formatSkillLine(s, { verbose: options.verbose }));
58333
58449
  }
58450
+ printSkillHint(page, searchCommand(query, options));
58334
58451
  }
58335
58452
  async function handleCategories(options) {
58336
58453
  const registry2 = await getBrowseRegistry({ all: true, remote: options.remote });
@@ -58359,11 +58476,60 @@ async function handleTags(options) {
58359
58476
  await writeJson(sorted, 2);
58360
58477
  return;
58361
58478
  }
58479
+ const page = paginate(sorted, {
58480
+ limit: parsePageLimit(options.limit, DEFAULT_TAG_LIMIT, { allowAll: true }),
58481
+ offset: parsePageOffset(options.cursor)
58482
+ });
58362
58483
  console.log(source_default.bold(`
58363
- Tags:
58484
+ Tags: ${showingLabel(sorted.length, page.items.length, page.offset)}
58364
58485
  `));
58365
- for (const { name, count } of sorted)
58486
+ for (const { name, count } of page.items)
58366
58487
  console.log(` ${source_default.cyan(name)} (${count})`);
58488
+ printPageHint(page, `skills tags${options.remote ? " --remote" : ""}`);
58489
+ }
58490
+ function printSkillHint(page, command) {
58491
+ printPageHint(page, command);
58492
+ console.log(source_default.dim(`Details: skills show <name> or rerun with --verbose. Use --json for the full machine-readable payload.`));
58493
+ }
58494
+ function printPageHint(page, command) {
58495
+ if (!page.hasMore || page.nextOffset === null)
58496
+ return;
58497
+ console.log(source_default.dim(`
58498
+ Next: ${command} --cursor ${page.nextOffset} --limit ${page.limit}`));
58499
+ }
58500
+ function listCommand(options) {
58501
+ const parts = ["skills list"];
58502
+ if (options.all)
58503
+ parts.push("--all");
58504
+ if (options.remote)
58505
+ parts.push("--remote");
58506
+ if (options.category)
58507
+ parts.push("--category", quoteArg(options.category));
58508
+ if (options.tags)
58509
+ parts.push("--tags", quoteArg(options.tags));
58510
+ if (options.pinned)
58511
+ parts.push("--pinned");
58512
+ return parts.join(" ");
58513
+ }
58514
+ function searchCommand(query, options) {
58515
+ const parts = ["skills search", quoteArg(query)];
58516
+ if (options.all)
58517
+ parts.push("--all");
58518
+ if (options.remote)
58519
+ parts.push("--remote");
58520
+ if (options.category)
58521
+ parts.push("--category", quoteArg(options.category));
58522
+ if (options.tags)
58523
+ parts.push("--tags", quoteArg(options.tags));
58524
+ return parts.join(" ");
58525
+ }
58526
+ function quoteArg(value) {
58527
+ return value.includes(" ") ? JSON.stringify(value) : value;
58528
+ }
58529
+ function skillCountLabel(total, shown, offset) {
58530
+ if (offset > 0 || shown < total)
58531
+ return `${shown} of ${total} skill(s), cursor ${offset}`;
58532
+ return `${total} skill(s)`;
58367
58533
  }
58368
58534
  var init_list = __esm(() => {
58369
58535
  init_source();
@@ -59305,7 +59471,7 @@ var exports_diagnostic = {};
59305
59471
  __export(exports_diagnostic, {
59306
59472
  registerDiagnostic: () => registerDiagnostic
59307
59473
  });
59308
- import { existsSync as existsSync13, readFileSync as readFileSync12, readdirSync as readdirSync4, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
59474
+ import { existsSync as existsSync13, readFileSync as readFileSync12, readdirSync as readdirSync5, statSync as statSync4, writeFileSync as writeFileSync6 } from "fs";
59309
59475
  import { join as join13 } from "path";
59310
59476
  import { execSync as execSync2 } from "child_process";
59311
59477
  function registerDiagnostic(parent) {
@@ -59511,7 +59677,7 @@ function handleWhoami(options) {
59511
59677
  let skillCount = 0;
59512
59678
  if (exists)
59513
59679
  try {
59514
- skillCount = readdirSync4(agentSkillsPath).filter((f) => !f.startsWith(".") && statSync3(join13(agentSkillsPath, f)).isDirectory()).length;
59680
+ skillCount = readdirSync5(agentSkillsPath).filter((f) => !f.startsWith(".") && statSync4(join13(agentSkillsPath, f)).isDirectory()).length;
59515
59681
  } catch {}
59516
59682
  agentConfigs.push({ agent, label: AGENT_LABELS[agent], path: agentSkillsPath, exists, skillCount });
59517
59683
  }
@@ -59644,7 +59810,7 @@ var REMOTE_SKILL_RUN_CONTRACT_VERSION = 1;
59644
59810
 
59645
59811
  // src/lib/run-state.ts
59646
59812
  import { createHash, randomBytes } from "crypto";
59647
- import { existsSync as existsSync14, mkdirSync as mkdirSync5, readFileSync as readFileSync13, readdirSync as readdirSync5, statSync as statSync4, writeFileSync as writeFileSync7 } from "fs";
59813
+ import { existsSync as existsSync14, mkdirSync as mkdirSync5, readFileSync as readFileSync13, readdirSync as readdirSync6, statSync as statSync5, writeFileSync as writeFileSync7 } from "fs";
59648
59814
  import { extname, join as join14, relative as relative2 } from "path";
59649
59815
  function createSkillRun(params, targetDir = process.cwd()) {
59650
59816
  const now3 = new Date;
@@ -59719,11 +59885,11 @@ function listSkillRuns(targetDir = process.cwd(), limit = 50) {
59719
59885
  if (!existsSync14(runsRoot))
59720
59886
  return [];
59721
59887
  const records = [];
59722
- for (const day of readdirSync5(runsRoot).sort().reverse()) {
59888
+ for (const day of readdirSync6(runsRoot).sort().reverse()) {
59723
59889
  const dayDir = join14(runsRoot, day);
59724
- if (!statSync4(dayDir).isDirectory())
59890
+ if (!statSync5(dayDir).isDirectory())
59725
59891
  continue;
59726
- for (const runId of readdirSync5(dayDir).sort().reverse()) {
59892
+ for (const runId of readdirSync6(dayDir).sort().reverse()) {
59727
59893
  const record2 = readRunRecord(join14(dayDir, runId));
59728
59894
  if (record2)
59729
59895
  records.push(record2);
@@ -59737,7 +59903,7 @@ function findSkillRun(runId, targetDir = process.cwd()) {
59737
59903
  const runsRoot = join14(getProjectStateDir(targetDir), "runs");
59738
59904
  if (!existsSync14(runsRoot))
59739
59905
  return null;
59740
- for (const day of readdirSync5(runsRoot)) {
59906
+ for (const day of readdirSync6(runsRoot)) {
59741
59907
  const record2 = readRunRecord(join14(runsRoot, day, runId));
59742
59908
  if (record2)
59743
59909
  return record2;
@@ -59760,7 +59926,7 @@ function collectRunArtifacts(context) {
59760
59926
  return [];
59761
59927
  const artifacts = [];
59762
59928
  for (const path of walkFiles(context.exportDir)) {
59763
- const stat = statSync4(path);
59929
+ const stat = statSync5(path);
59764
59930
  const bytes = readFileSync13(path);
59765
59931
  artifacts.push({
59766
59932
  path: toProjectRelative(context.targetDir, path),
@@ -59783,9 +59949,9 @@ function readRunRecord(runDir) {
59783
59949
  }
59784
59950
  function walkFiles(dir) {
59785
59951
  const files = [];
59786
- for (const entry of readdirSync5(dir)) {
59952
+ for (const entry of readdirSync6(dir)) {
59787
59953
  const full = join14(dir, entry);
59788
- if (statSync4(full).isDirectory())
59954
+ if (statSync5(full).isDirectory())
59789
59955
  files.push(...walkFiles(full));
59790
59956
  else
59791
59957
  files.push(full);
@@ -75177,18 +75343,29 @@ var init_mcp_contracts = __esm(() => {
75177
75343
  exitCode: { type: "number", description: "Process exit code for local runs." },
75178
75344
  skill: stringSchema("Canonical skill slug."),
75179
75345
  remote: { type: "boolean", description: "Whether the skill was submitted to the hosted runtime." },
75180
- stdout: stringSchema("Captured stdout for local runs."),
75181
- stderr: stringSchema("Captured stderr for local runs."),
75346
+ stdoutPreview: objectSchema({
75347
+ text: stringSchema("Truncated stdout preview."),
75348
+ length: { type: "number" },
75349
+ truncated: { type: "boolean" }
75350
+ }, [], "Default compact stdout preview."),
75351
+ stderrPreview: objectSchema({
75352
+ text: stringSchema("Truncated stderr preview."),
75353
+ length: { type: "number" },
75354
+ truncated: { type: "boolean" }
75355
+ }, [], "Default compact stderr preview."),
75356
+ stdout: stringSchema("Captured stdout for local runs when detail:true is requested."),
75357
+ stderr: stringSchema("Captured stderr for local runs when detail:true is requested."),
75182
75358
  id: stringSchema("Remote run id when submitted remotely."),
75183
75359
  localRunId: stringSchema("Local run metadata id."),
75184
75360
  status: stringSchema("Run lifecycle status."),
75185
75361
  pricing: pricingSchema,
75186
- remoteRun: objectSchema({}, [], "Normalized hosted remote run contract.", true),
75187
- run: objectSchema({}, [], "Local run metadata.", true),
75362
+ remoteRun: objectSchema({}, [], "Compact hosted remote run summary by default; full contract when detail:true is requested.", true),
75363
+ run: objectSchema({}, [], "Compact local run metadata by default; full metadata when detail:true is requested.", true),
75188
75364
  nextActions: objectSchema({
75189
75365
  poll: stringSchema("Command to poll run status."),
75190
75366
  download: stringSchema("Command to download artifacts.")
75191
- })
75367
+ }),
75368
+ detailHint: stringSchema("How to request the complete payload.")
75192
75369
  }, [], "Skill run result.");
75193
75370
  toolContracts = [
75194
75371
  {
@@ -75236,7 +75413,7 @@ var init_mcp_contracts = __esm(() => {
75236
75413
  {
75237
75414
  name: "list_skills",
75238
75415
  title: "List Skills",
75239
- description: "List skills from the basic or full registry profile.",
75416
+ description: "List skills from the basic or full registry profile. Returns a compact paged envelope by default.",
75240
75417
  params: ["category?", "profile?", "detail?", "limit?", "offset?"],
75241
75418
  category: "discovery",
75242
75419
  sideEffects: "none",
@@ -75252,7 +75429,11 @@ var init_mcp_contracts = __esm(() => {
75252
75429
  skills: arraySchema(skillSummarySchema),
75253
75430
  total: { type: "number" },
75254
75431
  offset: { type: "number" },
75255
- limit: { type: "number" }
75432
+ limit: { type: "number" },
75433
+ nextOffset: { type: "number" },
75434
+ hasMore: { type: "boolean" },
75435
+ nextArguments: objectSchema({}, [], "Arguments for the next page.", true),
75436
+ detailHint: stringSchema("How to request fuller skill objects.")
75256
75437
  })
75257
75438
  },
75258
75439
  {
@@ -75273,7 +75454,7 @@ var init_mcp_contracts = __esm(() => {
75273
75454
  {
75274
75455
  name: "search_skills",
75275
75456
  title: "Search Skills",
75276
- description: "Search skills by name, description, or tags.",
75457
+ description: "Search skills by name, description, or tags. Returns a compact paged envelope by default.",
75277
75458
  params: ["query", "profile?", "detail?", "limit?", "offset?"],
75278
75459
  category: "discovery",
75279
75460
  sideEffects: "none",
@@ -75285,7 +75466,16 @@ var init_mcp_contracts = __esm(() => {
75285
75466
  limit: { type: "number", minimum: 0 },
75286
75467
  offset: { type: "number", minimum: 0 }
75287
75468
  }, ["query"]),
75288
- outputSchema: objectSchema({ skills: arraySchema(skillSummarySchema) })
75469
+ outputSchema: objectSchema({
75470
+ skills: arraySchema(skillSummarySchema),
75471
+ total: { type: "number" },
75472
+ offset: { type: "number" },
75473
+ limit: { type: "number" },
75474
+ nextOffset: { type: "number" },
75475
+ hasMore: { type: "boolean" },
75476
+ nextArguments: objectSchema({}, [], "Arguments for the next page.", true),
75477
+ detailHint: stringSchema("How to request fuller skill objects.")
75478
+ })
75289
75479
  },
75290
75480
  {
75291
75481
  name: "get_skill_info",
@@ -75402,8 +75592,8 @@ var init_mcp_contracts = __esm(() => {
75402
75592
  {
75403
75593
  name: "run_skill",
75404
75594
  title: "Run Skill",
75405
- description: "Run a skill locally or through a configured remote runner.",
75406
- params: ["name", "input?", "args?", "approved?"],
75595
+ 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.",
75596
+ params: ["name", "input?", "args?", "approved?", "detail?"],
75407
75597
  category: "execution",
75408
75598
  sideEffects: "local-process-or-remote-run",
75409
75599
  stable: true,
@@ -75411,28 +75601,33 @@ var init_mcp_contracts = __esm(() => {
75411
75601
  name: skillNameInput,
75412
75602
  input: runInputSchema,
75413
75603
  args: runArgsSchema,
75414
- approved: paidRunApprovalSchema
75604
+ approved: paidRunApprovalSchema,
75605
+ detail: { type: "boolean", default: false, description: "Return full stdout/stderr, remote run, and local run metadata." }
75415
75606
  }, ["name"]),
75416
75607
  outputSchema: runOutputSchema
75417
75608
  },
75418
75609
  {
75419
75610
  name: "get_run_status",
75420
75611
  title: "Get Run Status",
75421
- description: "Fetch remote run status and next actions.",
75422
- params: ["run_id"],
75612
+ description: "Fetch remote run status and next actions. Returns a compact status summary by default; pass detail:true for the complete remote run payload.",
75613
+ params: ["run_id", "detail?"],
75423
75614
  category: "execution",
75424
75615
  sideEffects: "none",
75425
75616
  stable: true,
75426
- inputSchema: objectSchema({ run_id: stringSchema("Remote or local run id.") }, ["run_id"]),
75617
+ inputSchema: objectSchema({
75618
+ run_id: stringSchema("Remote or local run id."),
75619
+ detail: { type: "boolean", default: false, description: "Return the complete remote run payload." }
75620
+ }, ["run_id"]),
75427
75621
  outputSchema: objectSchema({
75428
75622
  contractVersion: { type: "number", description: "Remote run payload contract version." },
75429
75623
  runId: stringSchema("Remote run id."),
75430
75624
  localRunId: stringSchema("Local run id."),
75431
- run: objectSchema({}, [], "Normalized remote run status.", true),
75625
+ run: objectSchema({}, [], "Compact remote run status by default; full status when detail:true is requested.", true),
75432
75626
  nextActions: objectSchema({
75433
75627
  poll: stringSchema("Command to poll run status."),
75434
75628
  download: stringSchema("Command to download artifacts.")
75435
- })
75629
+ }),
75630
+ detailHint: stringSchema("How to request the complete payload.")
75436
75631
  })
75437
75632
  },
75438
75633
  {
@@ -75527,13 +75722,25 @@ var init_mcp_contracts = __esm(() => {
75527
75722
  {
75528
75723
  name: "list_schedules",
75529
75724
  title: "List Schedules",
75530
- description: "List scheduled skill runs.",
75531
- params: [],
75725
+ description: "List scheduled skill runs as a compact paged envelope.",
75726
+ params: ["limit?", "offset?"],
75532
75727
  category: "scheduling",
75533
75728
  sideEffects: "none",
75534
75729
  stable: true,
75535
- inputSchema: objectSchema(),
75536
- outputSchema: arraySchema(objectSchema({}, [], "Schedule record.", true))
75730
+ inputSchema: objectSchema({
75731
+ limit: { type: "number", minimum: 0 },
75732
+ offset: { type: "number", minimum: 0 }
75733
+ }),
75734
+ outputSchema: objectSchema({
75735
+ schedules: arraySchema(objectSchema({}, [], "Compact schedule record.", true)),
75736
+ total: { type: "number" },
75737
+ offset: { type: "number" },
75738
+ limit: { type: "number" },
75739
+ nextOffset: { type: "number" },
75740
+ hasMore: { type: "boolean" },
75741
+ nextArguments: objectSchema({}, [], "Arguments for the next page.", true),
75742
+ detailHint: stringSchema("How to request complete schedule details.")
75743
+ })
75537
75744
  },
75538
75745
  {
75539
75746
  name: "remove_schedule",
@@ -75745,7 +75952,7 @@ var init_helpers = __esm(() => {
75745
75952
  function registerDiscoveryTools(server) {
75746
75953
  server.registerTool("list_skills", {
75747
75954
  title: "List Skills",
75748
- 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.",
75955
+ 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.",
75749
75956
  inputSchema: {
75750
75957
  category: exports_external.string().optional(),
75751
75958
  profile: exports_external.enum(["basic", "all"]).optional(),
@@ -75757,16 +75964,20 @@ function registerDiscoveryTools(server) {
75757
75964
  const selectedProfile = profile || "basic";
75758
75965
  const skills = category ? loadRegistryProfile(selectedProfile).filter((s) => s.category === category) : loadRegistryProfile(selectedProfile);
75759
75966
  const mapped = detail ? skills.map(getPublicSkillDiscovery) : skills.map(getCompactSkillDiscovery);
75760
- if (limit !== undefined || offset !== undefined) {
75761
- const start = offset || 0;
75762
- const sliced = limit !== undefined ? mapped.slice(start, start + limit) : mapped.slice(start);
75763
- return {
75764
- content: [{ type: "text", text: JSON.stringify({ skills: sliced, total: mapped.length, offset: start, limit: limit ?? null }) }]
75765
- };
75766
- }
75767
- return {
75768
- content: [{ type: "text", text: JSON.stringify(mapped) }]
75769
- };
75967
+ const page = paginate(mapped, {
75968
+ limit: parsePageLimit(limit, DEFAULT_MCP_LIMIT, { max: 100 }),
75969
+ offset: parsePageOffset(offset)
75970
+ });
75971
+ return mcpJson({
75972
+ skills: page.items,
75973
+ total: page.total,
75974
+ offset: page.offset,
75975
+ limit: page.limit,
75976
+ nextOffset: page.nextOffset,
75977
+ hasMore: page.hasMore,
75978
+ nextArguments: page.hasMore ? { profile: selectedProfile, category, detail: Boolean(detail), limit: page.limit, offset: page.nextOffset } : null,
75979
+ detailHint: detail ? undefined : "Set detail:true for full public skill objects, or call get_skill_info for one skill."
75980
+ });
75770
75981
  });
75771
75982
  server.registerTool("list_pinned_skills", {
75772
75983
  title: "List Pinned Skills",
@@ -75783,7 +75994,7 @@ function registerDiscoveryTools(server) {
75783
75994
  });
75784
75995
  server.registerTool("search_skills", {
75785
75996
  title: "Search Skills",
75786
- 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.",
75997
+ 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.",
75787
75998
  inputSchema: {
75788
75999
  query: exports_external.string(),
75789
76000
  profile: exports_external.enum(["basic", "all"]).optional(),
@@ -75799,16 +76010,20 @@ function registerDiscoveryTools(server) {
75799
76010
  if (!cached2)
75800
76011
  cacheSet(cacheKey, results);
75801
76012
  const out = detail ? results.map(getPublicSkillDiscovery) : results.map(getCompactSkillDiscovery);
75802
- if (limit !== undefined || offset !== undefined) {
75803
- const start = offset || 0;
75804
- const sliced = limit !== undefined ? out.slice(start, start + limit) : out.slice(start);
75805
- return {
75806
- content: [{ type: "text", text: JSON.stringify({ skills: sliced, total: out.length, offset: start, limit: limit ?? null }) }]
75807
- };
75808
- }
75809
- return {
75810
- content: [{ type: "text", text: JSON.stringify(out) }]
75811
- };
76013
+ const page = paginate(out, {
76014
+ limit: parsePageLimit(limit, DEFAULT_MCP_LIMIT, { max: 100 }),
76015
+ offset: parsePageOffset(offset)
76016
+ });
76017
+ return mcpJson({
76018
+ skills: page.items,
76019
+ total: page.total,
76020
+ offset: page.offset,
76021
+ limit: page.limit,
76022
+ nextOffset: page.nextOffset,
76023
+ hasMore: page.hasMore,
76024
+ nextArguments: page.hasMore ? { query, profile: selectedProfile, detail: Boolean(detail), limit: page.limit, offset: page.nextOffset } : null,
76025
+ detailHint: detail ? undefined : "Set detail:true for full public skill objects, or call get_skill_info for one skill."
76026
+ });
75812
76027
  });
75813
76028
  server.registerTool("get_skill_info", {
75814
76029
  title: "Get Skill Info",
@@ -75953,7 +76168,7 @@ var init_remote_client = __esm(() => {
75953
76168
  });
75954
76169
 
75955
76170
  // src/mcp/operation-tools.ts
75956
- import { existsSync as existsSync15, readdirSync as readdirSync6, statSync as statSync5 } from "fs";
76171
+ import { existsSync as existsSync15, readdirSync as readdirSync7, statSync as statSync6 } from "fs";
75957
76172
  import { join as join15 } from "path";
75958
76173
  function registerOperationTools(server) {
75959
76174
  server.registerTool("scaffold_skill", {
@@ -76181,9 +76396,10 @@ function registerOperationTools(server) {
76181
76396
  name: exports_external.string(),
76182
76397
  input: exports_external.record(exports_external.string(), exports_external.unknown()).optional(),
76183
76398
  args: exports_external.array(exports_external.string()).optional(),
76184
- approved: exports_external.boolean().optional()
76399
+ approved: exports_external.boolean().optional(),
76400
+ detail: exports_external.boolean().optional()
76185
76401
  }
76186
- }, async ({ name, input, args, approved }) => {
76402
+ }, async ({ name, input, args, approved, detail }) => {
76187
76403
  const skill = getSkill(name);
76188
76404
  if (!skill) {
76189
76405
  return mcpError("SKILL_NOT_FOUND", `Skill '${name}' not found`, findSimilarSkills(name));
@@ -76249,7 +76465,7 @@ function registerOperationTools(server) {
76249
76465
  });
76250
76466
  writeRunLogs(runContext, "", "");
76251
76467
  const remoteRunId = typeof run.id === "string" ? run.id : undefined;
76252
- return mcpJson({
76468
+ const payload2 = {
76253
76469
  contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
76254
76470
  id: run.id,
76255
76471
  localRunId: localRun2.id,
@@ -76260,7 +76476,8 @@ function registerOperationTools(server) {
76260
76476
  remoteRun: run,
76261
76477
  run: localRun2,
76262
76478
  nextActions: remoteRunNextActions(remoteRunId)
76263
- });
76479
+ };
76480
+ return mcpJson(detail ? payload2 : compactRunToolPayload(payload2, "Call run_skill again with detail:true for full remote/local run records."));
76264
76481
  } catch (err) {
76265
76482
  const error48 = `Hosted skill ${skillName} requires hosted access: ${err.message}`;
76266
76483
  writeRunLogs(runContext, "", error48 + `
@@ -76282,23 +76499,23 @@ function registerOperationTools(server) {
76282
76499
  status: result2.exitCode === 0 ? "completed" : "failed",
76283
76500
  error: result2.error
76284
76501
  });
76502
+ const payload = { exitCode: result2.exitCode, skill: skillName, stdout: result2.stdout, stderr: result2.stderr, run: localRun };
76285
76503
  if (result2.error) {
76286
76504
  return {
76287
- content: [{ type: "text", text: JSON.stringify({ exitCode: result2.exitCode, error: result2.error, run: localRun }, null, 2) }],
76505
+ 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.")) }],
76288
76506
  isError: true
76289
76507
  };
76290
76508
  }
76291
- return {
76292
- content: [{ type: "text", text: JSON.stringify({ exitCode: result2.exitCode, skill: skillName, stdout: result2.stdout, stderr: result2.stderr, run: localRun }, null, 2) }]
76293
- };
76509
+ return mcpJson(detail ? payload : compactRunToolPayload(payload, "Call run_skill again with detail:true for full stdout/stderr and run metadata."));
76294
76510
  });
76295
76511
  server.registerTool("get_run_status", {
76296
76512
  title: "Get Run Status",
76297
76513
  description: "Fetch remote run status. Accepts a remote run id or a local run id linked to a remote run.",
76298
76514
  inputSchema: {
76299
- run_id: exports_external.string()
76515
+ run_id: exports_external.string(),
76516
+ detail: exports_external.boolean().optional()
76300
76517
  }
76301
- }, async ({ run_id }) => {
76518
+ }, async ({ run_id, detail }) => {
76302
76519
  const { getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_auth_store(), exports_auth_store));
76303
76520
  const apiKey = getApiKey2();
76304
76521
  if (!apiKey) {
@@ -76315,12 +76532,20 @@ function registerOperationTools(server) {
76315
76532
  const run = await client.getRun(remoteRunId);
76316
76533
  if (!run)
76317
76534
  return mcpError("RUN_NOT_FOUND", `Remote run '${remoteRunId}' not found`);
76318
- return mcpJson({
76535
+ const payload = {
76319
76536
  contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
76320
76537
  runId: remoteRunId,
76321
76538
  ...localRun ? { localRunId: localRun.id } : {},
76322
76539
  run,
76323
76540
  nextActions: remoteRunNextActions(remoteRunId)
76541
+ };
76542
+ return mcpJson(detail ? payload : {
76543
+ contractVersion: payload.contractVersion,
76544
+ runId: payload.runId,
76545
+ ...localRun ? { localRunId: localRun.id } : {},
76546
+ run: compactRemoteRun(run),
76547
+ nextActions: payload.nextActions,
76548
+ detailHint: "Call get_run_status with detail:true for the complete remote run payload."
76324
76549
  });
76325
76550
  } catch (err) {
76326
76551
  return mcpError("SKILLS_MD_ERROR", err.message);
@@ -76392,9 +76617,9 @@ function registerOperationTools(server) {
76392
76617
  let skillCount = 0;
76393
76618
  if (exists) {
76394
76619
  try {
76395
- skillCount = readdirSync6(agentSkillsPath).filter((f) => {
76620
+ skillCount = readdirSync7(agentSkillsPath).filter((f) => {
76396
76621
  const full = join15(agentSkillsPath, f);
76397
- return !f.startsWith(".") && statSync5(full).isDirectory();
76622
+ return !f.startsWith(".") && statSync6(full).isDirectory();
76398
76623
  }).length;
76399
76624
  } catch {}
76400
76625
  }
@@ -76412,6 +76637,32 @@ function registerOperationTools(server) {
76412
76637
  return { content: [{ type: "text", text: JSON.stringify(result2, null, 2) }] };
76413
76638
  });
76414
76639
  }
76640
+ function compactRunToolPayload(payload, detailHint) {
76641
+ const stdout = previewText(payload.stdout ?? "");
76642
+ const stderr = previewText(payload.stderr ?? "");
76643
+ return {
76644
+ ...payload.contractVersion !== undefined ? { contractVersion: payload.contractVersion } : {},
76645
+ ...payload.id !== undefined ? { id: payload.id } : {},
76646
+ ...payload.localRunId !== undefined ? { localRunId: payload.localRunId } : {},
76647
+ ...payload.exitCode !== undefined ? { exitCode: payload.exitCode } : {},
76648
+ skill: payload.skill,
76649
+ ...payload.status !== undefined ? { status: payload.status } : {},
76650
+ ...payload.remote !== undefined ? { remote: payload.remote } : {},
76651
+ ...payload.correlationId !== undefined ? { correlationId: payload.correlationId } : {},
76652
+ ...payload.pricing !== undefined ? { pricing: payload.pricing } : {},
76653
+ ...payload.error !== undefined ? { error: payload.error } : {},
76654
+ ...payload.remoteRun !== undefined ? { remoteRun: compactRemoteRun(payload.remoteRun) } : {},
76655
+ run: compactRunRecord(payload.run),
76656
+ stdoutPreview: stdout,
76657
+ stderrPreview: stderr,
76658
+ stdoutChars: stdout.length,
76659
+ stderrChars: stderr.length,
76660
+ stdoutTruncated: stdout.truncated,
76661
+ stderrTruncated: stderr.truncated,
76662
+ ...payload.nextActions !== undefined ? { nextActions: payload.nextActions } : {},
76663
+ detailHint
76664
+ };
76665
+ }
76415
76666
  var init_operation_tools = __esm(() => {
76416
76667
  init_zod();
76417
76668
  init_package();
@@ -76820,11 +77071,37 @@ function registerScheduleTools(server) {
76820
77071
  });
76821
77072
  server.registerTool("list_schedules", {
76822
77073
  title: "List Schedules",
76823
- description: "List all scheduled skill runs.",
76824
- inputSchema: {}
76825
- }, async () => {
77074
+ description: "List scheduled skill runs as a compact paged response. Use limit/offset for pagination.",
77075
+ inputSchema: {
77076
+ limit: exports_external.number().optional(),
77077
+ offset: exports_external.number().optional()
77078
+ }
77079
+ }, async ({ limit, offset }) => {
76826
77080
  const schedules = listSchedules();
76827
- return { content: [{ type: "text", text: JSON.stringify(schedules, null, 2) }] };
77081
+ const page = paginate(schedules, {
77082
+ limit: parsePageLimit(limit, DEFAULT_MCP_LIMIT, { max: 100 }),
77083
+ offset: parsePageOffset(offset)
77084
+ });
77085
+ return mcpJson({
77086
+ schedules: page.items.map((schedule) => ({
77087
+ id: schedule.id,
77088
+ name: schedule.name,
77089
+ skill: schedule.skill,
77090
+ cron: schedule.cron,
77091
+ enabled: schedule.enabled,
77092
+ lastRun: schedule.lastRun,
77093
+ lastRunStatus: schedule.lastRunStatus,
77094
+ nextRun: schedule.nextRun,
77095
+ argCount: schedule.args?.length ?? 0
77096
+ })),
77097
+ total: page.total,
77098
+ offset: page.offset,
77099
+ limit: page.limit,
77100
+ nextOffset: page.nextOffset,
77101
+ hasMore: page.hasMore,
77102
+ nextArguments: page.hasMore ? { limit: page.limit, offset: page.nextOffset } : null,
77103
+ detailHint: "Use schedule state files or future schedule detail commands for complete schedule records."
77104
+ });
76828
77105
  });
76829
77106
  server.registerTool("remove_schedule", {
76830
77107
  title: "Remove Schedule",
@@ -76880,6 +77157,7 @@ var init_schedule_tools = __esm(() => {
76880
77157
  init_portable_skills();
76881
77158
  init_scheduler();
76882
77159
  init_skill_validation();
77160
+ init_helpers();
76883
77161
  });
76884
77162
 
76885
77163
  // src/lib/native-storage.ts
@@ -76888,8 +77166,8 @@ import {
76888
77166
  existsSync as existsSync18,
76889
77167
  mkdirSync as mkdirSync8,
76890
77168
  readFileSync as readFileSync15,
76891
- readdirSync as readdirSync7,
76892
- statSync as statSync6,
77169
+ readdirSync as readdirSync8,
77170
+ statSync as statSync7,
76893
77171
  writeFileSync as writeFileSync9
76894
77172
  } from "fs";
76895
77173
  import { dirname as dirname5, join as join18, normalize as normalize3, relative as relative3, sep } from "path";
@@ -77024,9 +77302,9 @@ function parsePositiveInteger(value) {
77024
77302
  }
77025
77303
  function walkFiles2(dir) {
77026
77304
  const files = [];
77027
- for (const entry of readdirSync7(dir)) {
77305
+ for (const entry of readdirSync8(dir)) {
77028
77306
  const full = join18(dir, entry);
77029
- const stats = statSync6(full);
77307
+ const stats = statSync7(full);
77030
77308
  if (stats.isDirectory())
77031
77309
  files.push(...walkFiles2(full));
77032
77310
  else
@@ -77662,7 +77940,7 @@ function registerRuntime(parent) {
77662
77940
  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));
77663
77941
  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));
77664
77942
  const runs = parent.command("runs").description("Inspect local skill run records");
77665
- 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));
77943
+ 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));
77666
77944
  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));
77667
77945
  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));
77668
77946
  const exportsCommand = parent.command("exports").description("Inspect or open skill run exports");
@@ -78021,22 +78299,32 @@ function writeBlogArticleValidationError(errors4, json2) {
78021
78299
  process.exitCode = 1;
78022
78300
  }
78023
78301
  function handleRunsList(options) {
78024
- const limit = Number.parseInt(options.limit, 10);
78025
- const runs = listSkillRuns(process.cwd(), Number.isFinite(limit) ? limit : 20);
78026
78302
  if (options.json) {
78027
- console.log(JSON.stringify(runs, null, 2));
78303
+ const jsonLimit = Number.parseInt(options.limit, 10);
78304
+ const runs2 = listSkillRuns(process.cwd(), Number.isFinite(jsonLimit) ? jsonLimit : 20);
78305
+ console.log(JSON.stringify(runs2, null, 2));
78028
78306
  return;
78029
78307
  }
78308
+ const limit = parsePageLimit(options.limit, DEFAULT_LIST_LIMIT, { allowAll: true });
78309
+ const offset = parsePageOffset(options.cursor);
78310
+ const fetchLimit = Number.isFinite(limit) ? limit + offset + 1 : Number.POSITIVE_INFINITY;
78311
+ const runs = listSkillRuns(process.cwd(), Number.isFinite(fetchLimit) ? fetchLimit : 1e4);
78030
78312
  if (!runs.length) {
78031
78313
  console.log(source_default.dim("No skill runs found"));
78032
78314
  return;
78033
78315
  }
78316
+ const hasMoreThanFetched = Number.isFinite(limit) && runs.length > offset + limit;
78317
+ const page = paginate(hasMoreThanFetched ? runs.slice(0, offset + limit) : runs, { limit, offset });
78034
78318
  console.log(source_default.bold(`
78035
- Recent skill runs (${runs.length}):
78319
+ Recent skill runs (${showingLabel(hasMoreThanFetched ? offset + limit + 1 : runs.length, page.items.length, page.offset)}):
78036
78320
  `));
78037
- for (const run of runs) {
78038
- console.log(` ${source_default.cyan(run.id)} ${run.skill} ${statusColor(run.status)} ${source_default.dim(run.startedAt)}`);
78321
+ for (const run of page.items) {
78322
+ console.log(` ${source_default.cyan(run.id)} ${run.skill} ${statusColor(run.status)} ${source_default.dim(run.startedAt)} artifacts:${run.artifacts.length}`);
78039
78323
  }
78324
+ if (hasMoreThanFetched)
78325
+ console.log(source_default.dim(`
78326
+ Next: skills runs list --cursor ${offset + page.items.length} --limit ${page.limit}`));
78327
+ console.log(source_default.dim("Details: skills runs show <run-id> or use --json for full run records."));
78040
78328
  }
78041
78329
  function handleRunsShow(runId, options) {
78042
78330
  const run = findSkillRun(runId);
@@ -78828,7 +79116,7 @@ function registerSchedule(parent) {
78828
79116
  console.log(source_default.dim(` Next run: ${new Date(schedule.nextRun).toLocaleString()}`));
78829
79117
  console.log(source_default.dim(` ID: ${schedule.id}`));
78830
79118
  });
78831
- scheduleCmd.command("list").option("--json", "Output as JSON", false).description("List all scheduled skills").action((options) => {
79119
+ 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) => {
78832
79120
  const schedules = listSchedules();
78833
79121
  if (options.json) {
78834
79122
  console.log(JSON.stringify(schedules));
@@ -78838,15 +79126,25 @@ function registerSchedule(parent) {
78838
79126
  console.log(source_default.dim("No schedules. Run: skills schedule add <skill> <cron>"));
78839
79127
  return;
78840
79128
  }
79129
+ const page = paginate(schedules, {
79130
+ limit: parsePageLimit(options.limit, DEFAULT_LIST_LIMIT, { allowAll: true }),
79131
+ offset: parsePageOffset(options.cursor)
79132
+ });
78841
79133
  console.log(source_default.bold(`
78842
- Scheduled skills (${schedules.length}):
79134
+ Scheduled skills (${showingLabel(schedules.length, page.items.length, page.offset)}):
78843
79135
  `));
78844
- for (const s of schedules) {
79136
+ for (const s of page.items) {
78845
79137
  console.log(` ${source_default.cyan(s.name)} [${s.enabled ? source_default.green("enabled") : source_default.dim("disabled")}]`);
78846
79138
  const last2 = s.lastRun ? `last: ${new Date(s.lastRun).toLocaleString()} [${s.lastRunStatus ?? "?"}]` : "never run";
78847
79139
  const next = s.nextRun ? `next: ${new Date(s.nextRun).toLocaleString()}` : "";
78848
- console.log(source_default.dim(` skill: ${s.skill} cron: ${s.cron} ${last2} ${next}`));
79140
+ const args2 = s.args?.length ? ` args: ${truncateText(s.args.join(" "), 80)}` : "";
79141
+ console.log(source_default.dim(` ${s.id} skill: ${s.skill} cron: ${s.cron} ${last2} ${next}${args2}`));
78849
79142
  }
79143
+ if (page.hasMore && page.nextOffset !== null) {
79144
+ console.log(source_default.dim(`
79145
+ Next: skills schedule list --cursor ${page.nextOffset} --limit ${page.limit}`));
79146
+ }
79147
+ console.log(source_default.dim("Details: use --json for complete schedule records."));
78850
79148
  });
78851
79149
  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) => {
78852
79150
  const removed = removeSchedule(idOrName);
@@ -85315,9 +85613,15 @@ function print(value, json, text) {
85315
85613
  else
85316
85614
  console.log(text);
85317
85615
  }
85616
+ function hasJsonOption(options) {
85617
+ return Boolean(options?.json || options?.opts?.().json || options?.optsWithGlobals?.().json || options?.parent?.opts?.().json || options?.parent?.optsWithGlobals?.().json);
85618
+ }
85619
+ function wantsJson(actionOptions, command) {
85620
+ return hasJsonOption(actionOptions) || hasJsonOption(command);
85621
+ }
85318
85622
  function registerWebhookCommands(program2, options) {
85319
85623
  const webhooks = program2.command(options.webhooksCommandName ?? "webhooks").description("Manage Hasna event webhook subscriptions");
85320
- 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) => {
85624
+ 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) => {
85321
85625
  const timestamp = new Date().toISOString();
85322
85626
  const channel = {
85323
85627
  id: actionOptions.id,
@@ -85338,11 +85642,11 @@ function registerWebhookCommands(program2, options) {
85338
85642
  throw new Error(`Transport ${actionOptions.transport} is reserved for future use and cannot be added yet`);
85339
85643
  }
85340
85644
  const saved = await createClient(options).addChannel(channel);
85341
- print(sanitizeChannelForOutput(saved), Boolean(actionOptions.json), `Added ${saved.transport} channel ${saved.id}`);
85645
+ print(sanitizeChannelForOutput(saved), wantsJson(actionOptions, command), `Added ${saved.transport} channel ${saved.id}`);
85342
85646
  });
85343
- webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
85647
+ webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
85344
85648
  const channels = await createClient(options).listChannels();
85345
- if (actionOptions.json) {
85649
+ if (wantsJson(actionOptions, command)) {
85346
85650
  console.log(JSON.stringify(sanitizeChannelsForOutput(channels), null, 2));
85347
85651
  return;
85348
85652
  }
@@ -85354,11 +85658,11 @@ function registerWebhookCommands(program2, options) {
85354
85658
  console.log(`${channel.id} ${channel.enabled ? "enabled" : "disabled"} ${channel.transport} ${channel.webhook?.url ?? channel.command?.command ?? channel.transport}`);
85355
85659
  }
85356
85660
  });
85357
- webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions) => {
85661
+ webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
85358
85662
  const removed = await createClient(options).removeChannel(id);
85359
- print({ removed }, Boolean(actionOptions.json), removed ? `Removed ${id}` : `Channel not found: ${id}`);
85663
+ print({ removed }, wantsJson(actionOptions, command), removed ? `Removed ${id}` : `Channel not found: ${id}`);
85360
85664
  });
85361
- 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) => {
85665
+ 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) => {
85362
85666
  const result2 = await createClient(options).testChannel(id, {
85363
85667
  source: options.source,
85364
85668
  type: actionOptions.type,
@@ -85366,13 +85670,13 @@ function registerWebhookCommands(program2, options) {
85366
85670
  message: actionOptions.message,
85367
85671
  data: parseJsonObject(actionOptions.data, { test: true })
85368
85672
  });
85369
- print(result2, Boolean(actionOptions.json), `${result2.status}: ${result2.channelId}`);
85673
+ print(result2, wantsJson(actionOptions, command), `${result2.status}: ${result2.channelId}`);
85370
85674
  });
85371
85675
  return webhooks;
85372
85676
  }
85373
85677
  function registerEventCommands(program2, options) {
85374
85678
  const events = program2.command(options.eventsCommandName ?? "events").description("Emit, list, and replay Hasna events");
85375
- 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) => {
85679
+ 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) => {
85376
85680
  const result2 = await createClient(options).emit({
85377
85681
  source: actionOptions.source ?? options.source,
85378
85682
  type,
@@ -85383,9 +85687,9 @@ function registerEventCommands(program2, options) {
85383
85687
  data: parseJsonObject(actionOptions.data, {}),
85384
85688
  metadata: parseJsonObject(actionOptions.metadata, {})
85385
85689
  }, { deliver: actionOptions.deliver, dedupe: actionOptions.dedupe });
85386
- print(result2, Boolean(actionOptions.json), `${result2.deduped ? "Deduped" : "Emitted"} ${result2.event.id} to ${result2.deliveries.length} channel(s)`);
85690
+ print(result2, wantsJson(actionOptions, command), `${result2.deduped ? "Deduped" : "Emitted"} ${result2.event.id} to ${result2.deliveries.length} channel(s)`);
85387
85691
  });
85388
- 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) => {
85692
+ 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) => {
85389
85693
  let rows = await createClient(options).listEvents();
85390
85694
  if (actionOptions.source)
85391
85695
  rows = rows.filter((event) => event.source === actionOptions.source);
@@ -85393,7 +85697,7 @@ function registerEventCommands(program2, options) {
85393
85697
  rows = rows.filter((event) => event.type === actionOptions.type);
85394
85698
  if (actionOptions.limit)
85395
85699
  rows = rows.slice(-actionOptions.limit);
85396
- if (actionOptions.json) {
85700
+ if (wantsJson(actionOptions, command)) {
85397
85701
  console.log(JSON.stringify(rows, null, 2));
85398
85702
  return;
85399
85703
  }
@@ -85404,14 +85708,14 @@ function registerEventCommands(program2, options) {
85404
85708
  for (const event of rows)
85405
85709
  console.log(`${event.time} ${event.id} ${event.source} ${event.type} ${event.severity}`);
85406
85710
  });
85407
- 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) => {
85711
+ 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) => {
85408
85712
  const result2 = await createClient(options).replay({
85409
85713
  eventId: actionOptions.id,
85410
85714
  source: actionOptions.source,
85411
85715
  type: actionOptions.type,
85412
85716
  dryRun: actionOptions.dryRun
85413
85717
  });
85414
- print(result2, Boolean(actionOptions.json), `Replayed ${result2.events.length} event(s), ${result2.deliveries.length} delivery result(s)`);
85718
+ print(result2, wantsJson(actionOptions, command), `Replayed ${result2.events.length} event(s), ${result2.deliveries.length} delivery result(s)`);
85415
85719
  });
85416
85720
  return events;
85417
85721
  }