@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/README.md +32 -1
- package/bin/index.js +486 -182
- package/bin/mcp.js +311 -94
- package/dist/index.js +122 -59
- package/dist/lib/compact-output.d.ts +32 -0
- package/dist/lib/config.d.ts +1 -1
- package/dist/lib/skill-aliases.d.ts +1 -0
- package/dist/storage.js +28 -7
- package/package.json +2 -2
- package/skills/transcript/SKILL.md +53 -73
- package/skills/transcript/package.json +1 -1
- package/skills/apidocs/.claude/settings.json +0 -5
- package/skills/hook/bunfig.toml +0 -5
- package/skills/implementation/bunfig.toml +0 -5
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.
|
|
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.
|
|
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: ["
|
|
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
|
|
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 (
|
|
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 =
|
|
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
|
|
38821
|
+
readdirSync as readdirSync3,
|
|
38800
38822
|
rmSync,
|
|
38801
|
-
statSync as
|
|
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) || !
|
|
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
|
|
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) || !
|
|
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 (
|
|
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
|
|
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: "
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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
|
|
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} (${
|
|
58326
|
+
${category} (${showingLabel(output.length, page2.items.length, page2.offset)}):
|
|
58210
58327
|
`));
|
|
58211
|
-
for (const s of
|
|
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
|
|
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(", ")}] (${
|
|
58348
|
+
Skills matching tags [${tagFilter.join(", ")}] (${showingLabel(output.length, page2.items.length, page2.offset)}):
|
|
58229
58349
|
`));
|
|
58230
|
-
for (const s of
|
|
58231
|
-
console.log(
|
|
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
|
-
|
|
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
|
|
58261
|
-
|
|
58262
|
-
|
|
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
|
|
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}
|
|
58445
|
+
Found ${skillCountLabel(output.length, page.items.length, page.offset)} for "${query}":
|
|
58328
58446
|
`));
|
|
58329
|
-
for (const s of
|
|
58330
|
-
console.log(
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
59888
|
+
for (const day of readdirSync6(runsRoot).sort().reverse()) {
|
|
59723
59889
|
const dayDir = join14(runsRoot, day);
|
|
59724
|
-
if (!
|
|
59890
|
+
if (!statSync5(dayDir).isDirectory())
|
|
59725
59891
|
continue;
|
|
59726
|
-
for (const runId of
|
|
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
|
|
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 =
|
|
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
|
|
59952
|
+
for (const entry of readdirSync6(dir)) {
|
|
59787
59953
|
const full = join14(dir, entry);
|
|
59788
|
-
if (
|
|
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
|
-
|
|
75181
|
-
|
|
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({}, [], "
|
|
75187
|
-
run: objectSchema({}, [], "
|
|
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({
|
|
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({
|
|
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({}, [], "
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
75761
|
-
|
|
75762
|
-
|
|
75763
|
-
|
|
75764
|
-
|
|
75765
|
-
|
|
75766
|
-
|
|
75767
|
-
|
|
75768
|
-
|
|
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
|
|
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
|
-
|
|
75803
|
-
|
|
75804
|
-
|
|
75805
|
-
|
|
75806
|
-
|
|
75807
|
-
|
|
75808
|
-
|
|
75809
|
-
|
|
75810
|
-
|
|
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
|
|
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
|
-
|
|
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({
|
|
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
|
-
|
|
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 =
|
|
76620
|
+
skillCount = readdirSync7(agentSkillsPath).filter((f) => {
|
|
76396
76621
|
const full = join15(agentSkillsPath, f);
|
|
76397
|
-
return !f.startsWith(".") &&
|
|
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
|
|
76824
|
-
inputSchema: {
|
|
76825
|
-
|
|
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
|
-
|
|
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
|
|
76892
|
-
statSync as
|
|
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
|
|
77305
|
+
for (const entry of readdirSync8(dir)) {
|
|
77028
77306
|
const full = join18(dir, entry);
|
|
77029
|
-
const stats =
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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),
|
|
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
|
|
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 },
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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
|
}
|