@hasna/skills 0.1.45 → 0.1.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -1
- package/bin/index.js +469 -151
- package/bin/mcp.js +299 -68
- package/dist/index.js +108 -31
- package/dist/lib/compact-output.d.ts +32 -0
- package/dist/lib/skill-aliases.d.ts +1 -0
- 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/mcp.js
CHANGED
|
@@ -6625,7 +6625,8 @@ var init_skill_aliases = __esm(() => {
|
|
|
6625
6625
|
"pdf-reader": "read-pdf",
|
|
6626
6626
|
"generate-image": "image",
|
|
6627
6627
|
"image-generator": "image",
|
|
6628
|
-
"create-blog-article": "blog-article"
|
|
6628
|
+
"create-blog-article": "blog-article",
|
|
6629
|
+
"skill-diff": "diff-viewer"
|
|
6629
6630
|
};
|
|
6630
6631
|
});
|
|
6631
6632
|
|
|
@@ -7042,7 +7043,7 @@ var init_pricing = __esm(() => {
|
|
|
7042
7043
|
{ 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" },
|
|
7043
7044
|
{ slug: "generate-book-cover", displayName: "Book Cover", tier: "premium", costCents: 20, providers: ["gpt-image-2"], description: "Professional book cover design from title and genre" },
|
|
7044
7045
|
{ slug: "remove-background", displayName: "Remove Background", tier: "premium", costCents: 10, providers: ["gemini-3-pro"], description: "AI-powered background removal from images" },
|
|
7045
|
-
{ slug: "transcript", displayName: "Transcript", tier: "premium", costCents: 10, providers: ["
|
|
7046
|
+
{ slug: "transcript", displayName: "Transcript", tier: "premium", costCents: 10, providers: ["openai", "elevenlabs", "deepgram", "hosted"], description: "Audio/video transcription with timestamps, diarization, and URL support" },
|
|
7046
7047
|
{ slug: "webcrawling", displayName: "Web Crawling", tier: "premium", costCents: 5, providers: ["firecrawl"], description: "Structured web page crawling and extraction" },
|
|
7047
7048
|
{ slug: "browse", displayName: "Browse", tier: "premium", costCents: 5, providers: ["browser"], description: "Web browsing and page interaction" },
|
|
7048
7049
|
{ slug: "read-pdf", displayName: "Read PDF", tier: "premium", costCents: 5, providers: ["cerebras"], description: "Hosted PDF extraction and structured content analysis" },
|
|
@@ -18269,7 +18270,7 @@ function finalize(ctx, schema) {
|
|
|
18269
18270
|
result.$schema = "http://json-schema.org/draft-07/schema#";
|
|
18270
18271
|
} else if (ctx.target === "draft-04") {
|
|
18271
18272
|
result.$schema = "http://json-schema.org/draft-04/schema#";
|
|
18272
|
-
} else if (ctx.target === "openapi-3.0") {}
|
|
18273
|
+
} else if (ctx.target === "openapi-3.0") {} else {}
|
|
18273
18274
|
if (ctx.external?.uri) {
|
|
18274
18275
|
const id = ctx.external.registry.get(schema)?.id;
|
|
18275
18276
|
if (!id)
|
|
@@ -18517,7 +18518,7 @@ var literalProcessor = (schema, ctx, json, _params) => {
|
|
|
18517
18518
|
if (val === undefined) {
|
|
18518
18519
|
if (ctx.unrepresentable === "throw") {
|
|
18519
18520
|
throw new Error("Literal `undefined` cannot be represented in JSON Schema");
|
|
18520
|
-
}
|
|
18521
|
+
} else {}
|
|
18521
18522
|
} else if (typeof val === "bigint") {
|
|
18522
18523
|
if (ctx.unrepresentable === "throw") {
|
|
18523
18524
|
throw new Error("BigInt literals cannot be represented in JSON Schema");
|
|
@@ -21797,7 +21798,7 @@ class StdioServerTransport {
|
|
|
21797
21798
|
// package.json
|
|
21798
21799
|
var package_default = {
|
|
21799
21800
|
name: "@hasna/skills",
|
|
21800
|
-
version: "0.1.
|
|
21801
|
+
version: "0.1.47",
|
|
21801
21802
|
description: "Skills library for AI coding agents",
|
|
21802
21803
|
type: "module",
|
|
21803
21804
|
bin: {
|
|
@@ -21866,7 +21867,7 @@ var package_default = {
|
|
|
21866
21867
|
typescript: "^5"
|
|
21867
21868
|
},
|
|
21868
21869
|
dependencies: {
|
|
21869
|
-
"@hasna/events": "^0.1.
|
|
21870
|
+
"@hasna/events": "^0.1.7",
|
|
21870
21871
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
21871
21872
|
chalk: "^5.3.0",
|
|
21872
21873
|
commander: "^12.1.0",
|
|
@@ -30121,12 +30122,47 @@ function ensurePortableSkillFiles(skillPath, manifest) {
|
|
|
30121
30122
|
writeFileSync2(join3(skillPath, "skill.json"), renderSkillJson(next));
|
|
30122
30123
|
if (!existsSync3(join3(skillPath, "AGENTS.md")))
|
|
30123
30124
|
writeFileSync2(join3(skillPath, "AGENTS.md"), renderAgentsMd(next));
|
|
30124
|
-
|
|
30125
|
-
writeFileSync2(join3(skillPath, "package.json"), renderPackageJson(next));
|
|
30125
|
+
ensurePackageJson(skillPath, next);
|
|
30126
30126
|
if (!existsSync3(join3(skillPath, "tsconfig.json")))
|
|
30127
30127
|
writeFileSync2(join3(skillPath, "tsconfig.json"), renderTsconfig());
|
|
30128
30128
|
return readPortableSkillManifest(skillPath, next.name);
|
|
30129
30129
|
}
|
|
30130
|
+
function ensurePackageJson(skillPath, manifest) {
|
|
30131
|
+
const pkgPath = join3(skillPath, "package.json");
|
|
30132
|
+
const first = manifest.commands[0] ?? { name: manifest.name, entry: "src/index.ts" };
|
|
30133
|
+
const commandName = normalizePortableSkillName(first.name || manifest.name);
|
|
30134
|
+
const entry = (first.entry ?? "src/index.ts").replace(/^\.\//, "");
|
|
30135
|
+
if (!existsSync3(pkgPath)) {
|
|
30136
|
+
writeFileSync2(pkgPath, renderPackageJson(manifest));
|
|
30137
|
+
return;
|
|
30138
|
+
}
|
|
30139
|
+
const existing = readJsonObject(pkgPath);
|
|
30140
|
+
const bin = {};
|
|
30141
|
+
if (isRecord(existing.bin)) {
|
|
30142
|
+
for (const [name, value] of Object.entries(existing.bin)) {
|
|
30143
|
+
if (typeof value === "string" && value.trim())
|
|
30144
|
+
bin[normalizePortableSkillName(name)] = value.replace(/^\.\//, "");
|
|
30145
|
+
}
|
|
30146
|
+
} else {
|
|
30147
|
+
const binEntry = stringValue(existing.bin);
|
|
30148
|
+
if (binEntry)
|
|
30149
|
+
bin[manifest.name] = binEntry.replace(/^\.\//, "");
|
|
30150
|
+
}
|
|
30151
|
+
bin[commandName] = entry;
|
|
30152
|
+
const scripts = isRecord(existing.scripts) ? { ...existing.scripts } : {};
|
|
30153
|
+
if (!stringValue(scripts.dev))
|
|
30154
|
+
scripts.dev = `bun run ${entry}`;
|
|
30155
|
+
writeFileSync2(pkgPath, `${JSON.stringify({
|
|
30156
|
+
...existing,
|
|
30157
|
+
name: manifest.name,
|
|
30158
|
+
version: manifest.version,
|
|
30159
|
+
description: manifest.description,
|
|
30160
|
+
type: stringValue(existing.type) ?? "module",
|
|
30161
|
+
bin,
|
|
30162
|
+
scripts
|
|
30163
|
+
}, null, 2)}
|
|
30164
|
+
`);
|
|
30165
|
+
}
|
|
30130
30166
|
function copySkillDirectory(source, destination) {
|
|
30131
30167
|
mkdirSync2(destination, { recursive: true });
|
|
30132
30168
|
cpSync(source, destination, {
|
|
@@ -31566,9 +31602,9 @@ var MEDIA_PROCESSING_SKILLS = [
|
|
|
31566
31602
|
{
|
|
31567
31603
|
name: "transcript",
|
|
31568
31604
|
displayName: "Transcript",
|
|
31569
|
-
description: "
|
|
31605
|
+
description: "Transcribe audio, video, and media URLs with OpenAI GPT-4o, ElevenLabs Scribe v2, DeepGram, or hosted runtime",
|
|
31570
31606
|
category: "Media Processing",
|
|
31571
|
-
tags: ["transcript", "audio", "video", "speech-to-text"]
|
|
31607
|
+
tags: ["transcript", "audio", "video", "speech-to-text", "diarization", "youtube"]
|
|
31572
31608
|
},
|
|
31573
31609
|
{
|
|
31574
31610
|
name: "video-cut-suggester",
|
|
@@ -33012,18 +33048,29 @@ var runOutputSchema = objectSchema({
|
|
|
33012
33048
|
exitCode: { type: "number", description: "Process exit code for local runs." },
|
|
33013
33049
|
skill: stringSchema("Canonical skill slug."),
|
|
33014
33050
|
remote: { type: "boolean", description: "Whether the skill was submitted to the hosted runtime." },
|
|
33015
|
-
|
|
33016
|
-
|
|
33051
|
+
stdoutPreview: objectSchema({
|
|
33052
|
+
text: stringSchema("Truncated stdout preview."),
|
|
33053
|
+
length: { type: "number" },
|
|
33054
|
+
truncated: { type: "boolean" }
|
|
33055
|
+
}, [], "Default compact stdout preview."),
|
|
33056
|
+
stderrPreview: objectSchema({
|
|
33057
|
+
text: stringSchema("Truncated stderr preview."),
|
|
33058
|
+
length: { type: "number" },
|
|
33059
|
+
truncated: { type: "boolean" }
|
|
33060
|
+
}, [], "Default compact stderr preview."),
|
|
33061
|
+
stdout: stringSchema("Captured stdout for local runs when detail:true is requested."),
|
|
33062
|
+
stderr: stringSchema("Captured stderr for local runs when detail:true is requested."),
|
|
33017
33063
|
id: stringSchema("Remote run id when submitted remotely."),
|
|
33018
33064
|
localRunId: stringSchema("Local run metadata id."),
|
|
33019
33065
|
status: stringSchema("Run lifecycle status."),
|
|
33020
33066
|
pricing: pricingSchema,
|
|
33021
|
-
remoteRun: objectSchema({}, [], "
|
|
33022
|
-
run: objectSchema({}, [], "
|
|
33067
|
+
remoteRun: objectSchema({}, [], "Compact hosted remote run summary by default; full contract when detail:true is requested.", true),
|
|
33068
|
+
run: objectSchema({}, [], "Compact local run metadata by default; full metadata when detail:true is requested.", true),
|
|
33023
33069
|
nextActions: objectSchema({
|
|
33024
33070
|
poll: stringSchema("Command to poll run status."),
|
|
33025
33071
|
download: stringSchema("Command to download artifacts.")
|
|
33026
|
-
})
|
|
33072
|
+
}),
|
|
33073
|
+
detailHint: stringSchema("How to request the complete payload.")
|
|
33027
33074
|
}, [], "Skill run result.");
|
|
33028
33075
|
var toolContracts = [
|
|
33029
33076
|
{
|
|
@@ -33071,7 +33118,7 @@ var toolContracts = [
|
|
|
33071
33118
|
{
|
|
33072
33119
|
name: "list_skills",
|
|
33073
33120
|
title: "List Skills",
|
|
33074
|
-
description: "List skills from the basic or full registry profile.",
|
|
33121
|
+
description: "List skills from the basic or full registry profile. Returns a compact paged envelope by default.",
|
|
33075
33122
|
params: ["category?", "profile?", "detail?", "limit?", "offset?"],
|
|
33076
33123
|
category: "discovery",
|
|
33077
33124
|
sideEffects: "none",
|
|
@@ -33087,7 +33134,11 @@ var toolContracts = [
|
|
|
33087
33134
|
skills: arraySchema(skillSummarySchema),
|
|
33088
33135
|
total: { type: "number" },
|
|
33089
33136
|
offset: { type: "number" },
|
|
33090
|
-
limit: { type: "number" }
|
|
33137
|
+
limit: { type: "number" },
|
|
33138
|
+
nextOffset: { type: "number" },
|
|
33139
|
+
hasMore: { type: "boolean" },
|
|
33140
|
+
nextArguments: objectSchema({}, [], "Arguments for the next page.", true),
|
|
33141
|
+
detailHint: stringSchema("How to request fuller skill objects.")
|
|
33091
33142
|
})
|
|
33092
33143
|
},
|
|
33093
33144
|
{
|
|
@@ -33108,7 +33159,7 @@ var toolContracts = [
|
|
|
33108
33159
|
{
|
|
33109
33160
|
name: "search_skills",
|
|
33110
33161
|
title: "Search Skills",
|
|
33111
|
-
description: "Search skills by name, description, or tags.",
|
|
33162
|
+
description: "Search skills by name, description, or tags. Returns a compact paged envelope by default.",
|
|
33112
33163
|
params: ["query", "profile?", "detail?", "limit?", "offset?"],
|
|
33113
33164
|
category: "discovery",
|
|
33114
33165
|
sideEffects: "none",
|
|
@@ -33120,7 +33171,16 @@ var toolContracts = [
|
|
|
33120
33171
|
limit: { type: "number", minimum: 0 },
|
|
33121
33172
|
offset: { type: "number", minimum: 0 }
|
|
33122
33173
|
}, ["query"]),
|
|
33123
|
-
outputSchema: objectSchema({
|
|
33174
|
+
outputSchema: objectSchema({
|
|
33175
|
+
skills: arraySchema(skillSummarySchema),
|
|
33176
|
+
total: { type: "number" },
|
|
33177
|
+
offset: { type: "number" },
|
|
33178
|
+
limit: { type: "number" },
|
|
33179
|
+
nextOffset: { type: "number" },
|
|
33180
|
+
hasMore: { type: "boolean" },
|
|
33181
|
+
nextArguments: objectSchema({}, [], "Arguments for the next page.", true),
|
|
33182
|
+
detailHint: stringSchema("How to request fuller skill objects.")
|
|
33183
|
+
})
|
|
33124
33184
|
},
|
|
33125
33185
|
{
|
|
33126
33186
|
name: "get_skill_info",
|
|
@@ -33237,8 +33297,8 @@ var toolContracts = [
|
|
|
33237
33297
|
{
|
|
33238
33298
|
name: "run_skill",
|
|
33239
33299
|
title: "Run Skill",
|
|
33240
|
-
description: "Run a skill locally or through a configured remote runner.",
|
|
33241
|
-
params: ["name", "input?", "args?", "approved?"],
|
|
33300
|
+
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.",
|
|
33301
|
+
params: ["name", "input?", "args?", "approved?", "detail?"],
|
|
33242
33302
|
category: "execution",
|
|
33243
33303
|
sideEffects: "local-process-or-remote-run",
|
|
33244
33304
|
stable: true,
|
|
@@ -33246,28 +33306,33 @@ var toolContracts = [
|
|
|
33246
33306
|
name: skillNameInput,
|
|
33247
33307
|
input: runInputSchema,
|
|
33248
33308
|
args: runArgsSchema,
|
|
33249
|
-
approved: paidRunApprovalSchema
|
|
33309
|
+
approved: paidRunApprovalSchema,
|
|
33310
|
+
detail: { type: "boolean", default: false, description: "Return full stdout/stderr, remote run, and local run metadata." }
|
|
33250
33311
|
}, ["name"]),
|
|
33251
33312
|
outputSchema: runOutputSchema
|
|
33252
33313
|
},
|
|
33253
33314
|
{
|
|
33254
33315
|
name: "get_run_status",
|
|
33255
33316
|
title: "Get Run Status",
|
|
33256
|
-
description: "Fetch remote run status and next actions.",
|
|
33257
|
-
params: ["run_id"],
|
|
33317
|
+
description: "Fetch remote run status and next actions. Returns a compact status summary by default; pass detail:true for the complete remote run payload.",
|
|
33318
|
+
params: ["run_id", "detail?"],
|
|
33258
33319
|
category: "execution",
|
|
33259
33320
|
sideEffects: "none",
|
|
33260
33321
|
stable: true,
|
|
33261
|
-
inputSchema: objectSchema({
|
|
33322
|
+
inputSchema: objectSchema({
|
|
33323
|
+
run_id: stringSchema("Remote or local run id."),
|
|
33324
|
+
detail: { type: "boolean", default: false, description: "Return the complete remote run payload." }
|
|
33325
|
+
}, ["run_id"]),
|
|
33262
33326
|
outputSchema: objectSchema({
|
|
33263
33327
|
contractVersion: { type: "number", description: "Remote run payload contract version." },
|
|
33264
33328
|
runId: stringSchema("Remote run id."),
|
|
33265
33329
|
localRunId: stringSchema("Local run id."),
|
|
33266
|
-
run: objectSchema({}, [], "
|
|
33330
|
+
run: objectSchema({}, [], "Compact remote run status by default; full status when detail:true is requested.", true),
|
|
33267
33331
|
nextActions: objectSchema({
|
|
33268
33332
|
poll: stringSchema("Command to poll run status."),
|
|
33269
33333
|
download: stringSchema("Command to download artifacts.")
|
|
33270
|
-
})
|
|
33334
|
+
}),
|
|
33335
|
+
detailHint: stringSchema("How to request the complete payload.")
|
|
33271
33336
|
})
|
|
33272
33337
|
},
|
|
33273
33338
|
{
|
|
@@ -33362,13 +33427,25 @@ var toolContracts = [
|
|
|
33362
33427
|
{
|
|
33363
33428
|
name: "list_schedules",
|
|
33364
33429
|
title: "List Schedules",
|
|
33365
|
-
description: "List scheduled skill runs.",
|
|
33366
|
-
params: [],
|
|
33430
|
+
description: "List scheduled skill runs as a compact paged envelope.",
|
|
33431
|
+
params: ["limit?", "offset?"],
|
|
33367
33432
|
category: "scheduling",
|
|
33368
33433
|
sideEffects: "none",
|
|
33369
33434
|
stable: true,
|
|
33370
|
-
inputSchema: objectSchema(
|
|
33371
|
-
|
|
33435
|
+
inputSchema: objectSchema({
|
|
33436
|
+
limit: { type: "number", minimum: 0 },
|
|
33437
|
+
offset: { type: "number", minimum: 0 }
|
|
33438
|
+
}),
|
|
33439
|
+
outputSchema: objectSchema({
|
|
33440
|
+
schedules: arraySchema(objectSchema({}, [], "Compact schedule record.", true)),
|
|
33441
|
+
total: { type: "number" },
|
|
33442
|
+
offset: { type: "number" },
|
|
33443
|
+
limit: { type: "number" },
|
|
33444
|
+
nextOffset: { type: "number" },
|
|
33445
|
+
hasMore: { type: "boolean" },
|
|
33446
|
+
nextArguments: objectSchema({}, [], "Arguments for the next page.", true),
|
|
33447
|
+
detailHint: stringSchema("How to request complete schedule details.")
|
|
33448
|
+
})
|
|
33372
33449
|
},
|
|
33373
33450
|
{
|
|
33374
33451
|
name: "remove_schedule",
|
|
@@ -33775,6 +33852,90 @@ function resolveDiscoveryPricing(skill) {
|
|
|
33775
33852
|
return skill.pricing && typeof skill.pricing.formattedCost === "string" ? skill.pricing : getPublicSkillPricing(skill.name);
|
|
33776
33853
|
}
|
|
33777
33854
|
|
|
33855
|
+
// src/lib/compact-output.ts
|
|
33856
|
+
var DEFAULT_MCP_LIMIT = 25;
|
|
33857
|
+
var MAX_PAGE_LIMIT = 200;
|
|
33858
|
+
var DEFAULT_PREVIEW_CHARS = 600;
|
|
33859
|
+
function truncateText(value, maxChars = 96) {
|
|
33860
|
+
const text = String(value ?? "").replace(/\s+/g, " ").trim();
|
|
33861
|
+
if (text.length <= maxChars)
|
|
33862
|
+
return text;
|
|
33863
|
+
return `${text.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
|
|
33864
|
+
}
|
|
33865
|
+
function previewText(value, maxChars = DEFAULT_PREVIEW_CHARS) {
|
|
33866
|
+
const text = String(value ?? "");
|
|
33867
|
+
return {
|
|
33868
|
+
text: text.length > maxChars ? `${text.slice(0, Math.max(0, maxChars - 3))}...` : text,
|
|
33869
|
+
length: text.length,
|
|
33870
|
+
truncated: text.length > maxChars
|
|
33871
|
+
};
|
|
33872
|
+
}
|
|
33873
|
+
function parsePageLimit(value, fallback, options = {}) {
|
|
33874
|
+
const max = options.max ?? MAX_PAGE_LIMIT;
|
|
33875
|
+
if (typeof value === "string" && options.allowAll && value.trim().toLowerCase() === "all") {
|
|
33876
|
+
return Number.POSITIVE_INFINITY;
|
|
33877
|
+
}
|
|
33878
|
+
const parsed = typeof value === "number" ? value : Number.parseInt(value ?? "", 10);
|
|
33879
|
+
if (!Number.isFinite(parsed))
|
|
33880
|
+
return fallback;
|
|
33881
|
+
if (options.allowAll && parsed === 0)
|
|
33882
|
+
return Number.POSITIVE_INFINITY;
|
|
33883
|
+
if (parsed <= 0)
|
|
33884
|
+
return fallback;
|
|
33885
|
+
return Math.min(parsed, max);
|
|
33886
|
+
}
|
|
33887
|
+
function parsePageOffset(value, fallback = 0) {
|
|
33888
|
+
const parsed = typeof value === "number" ? value : Number.parseInt(value ?? "", 10);
|
|
33889
|
+
if (!Number.isFinite(parsed) || parsed < 0)
|
|
33890
|
+
return fallback;
|
|
33891
|
+
return parsed;
|
|
33892
|
+
}
|
|
33893
|
+
function paginate(items, options) {
|
|
33894
|
+
const offset = Math.min(parsePageOffset(options.offset), items.length);
|
|
33895
|
+
const effectiveLimit = Number.isFinite(options.limit) ? Math.max(0, Math.min(options.limit, MAX_PAGE_LIMIT)) : Math.max(0, items.length - offset);
|
|
33896
|
+
const pageItems = items.slice(offset, offset + effectiveLimit);
|
|
33897
|
+
const nextOffset = offset + pageItems.length < items.length ? offset + pageItems.length : null;
|
|
33898
|
+
return {
|
|
33899
|
+
items: pageItems,
|
|
33900
|
+
total: items.length,
|
|
33901
|
+
offset,
|
|
33902
|
+
limit: effectiveLimit,
|
|
33903
|
+
hasMore: nextOffset !== null,
|
|
33904
|
+
nextOffset
|
|
33905
|
+
};
|
|
33906
|
+
}
|
|
33907
|
+
function compactRunRecord(run) {
|
|
33908
|
+
if (!run || typeof run !== "object")
|
|
33909
|
+
return {};
|
|
33910
|
+
return {
|
|
33911
|
+
id: run.id,
|
|
33912
|
+
skill: run.skill,
|
|
33913
|
+
status: run.status,
|
|
33914
|
+
startedAt: run.startedAt,
|
|
33915
|
+
...run.completedAt ? { completedAt: run.completedAt } : {},
|
|
33916
|
+
...run.remoteRunId ? { remoteRunId: run.remoteRunId } : {},
|
|
33917
|
+
...run.costCents !== undefined ? { costCents: run.costCents } : {},
|
|
33918
|
+
...run.error ? { error: truncateText(run.error, 240) } : {},
|
|
33919
|
+
artifactCount: Array.isArray(run.artifacts) ? run.artifacts.length : 0,
|
|
33920
|
+
paths: run.paths
|
|
33921
|
+
};
|
|
33922
|
+
}
|
|
33923
|
+
function compactRemoteRun(run) {
|
|
33924
|
+
if (!run || typeof run !== "object")
|
|
33925
|
+
return {};
|
|
33926
|
+
return {
|
|
33927
|
+
...run.contractVersion !== undefined ? { contractVersion: run.contractVersion } : {},
|
|
33928
|
+
id: run.id,
|
|
33929
|
+
skill: run.skill ?? run.requestedSlug,
|
|
33930
|
+
status: run.status,
|
|
33931
|
+
...run.correlationId ? { correlationId: run.correlationId } : {},
|
|
33932
|
+
...run.createdAt ? { createdAt: run.createdAt } : {},
|
|
33933
|
+
...run.startedAt ? { startedAt: run.startedAt } : {},
|
|
33934
|
+
...run.completedAt ? { completedAt: run.completedAt } : {},
|
|
33935
|
+
...run.error || run.errorMessage ? { error: truncateText(run.error ?? run.errorMessage, 240) } : {}
|
|
33936
|
+
};
|
|
33937
|
+
}
|
|
33938
|
+
|
|
33778
33939
|
// src/mcp/helpers.ts
|
|
33779
33940
|
function stripNulls(obj) {
|
|
33780
33941
|
return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== null && v !== undefined && !(Array.isArray(v) && v.length === 0)));
|
|
@@ -33823,7 +33984,7 @@ var TOOL_DESCRIPTIONS = getMcpToolDescriptions();
|
|
|
33823
33984
|
function registerDiscoveryTools(server) {
|
|
33824
33985
|
server.registerTool("list_skills", {
|
|
33825
33986
|
title: "List Skills",
|
|
33826
|
-
description: "List skills with public pricing. Defaults to the
|
|
33987
|
+
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.",
|
|
33827
33988
|
inputSchema: {
|
|
33828
33989
|
category: exports_external.string().optional(),
|
|
33829
33990
|
profile: exports_external.enum(["basic", "all"]).optional(),
|
|
@@ -33835,16 +33996,20 @@ function registerDiscoveryTools(server) {
|
|
|
33835
33996
|
const selectedProfile = profile || "basic";
|
|
33836
33997
|
const skills = category ? loadRegistryProfile(selectedProfile).filter((s) => s.category === category) : loadRegistryProfile(selectedProfile);
|
|
33837
33998
|
const mapped = detail ? skills.map(getPublicSkillDiscovery) : skills.map(getCompactSkillDiscovery);
|
|
33838
|
-
|
|
33839
|
-
|
|
33840
|
-
|
|
33841
|
-
|
|
33842
|
-
|
|
33843
|
-
|
|
33844
|
-
|
|
33845
|
-
|
|
33846
|
-
|
|
33847
|
-
|
|
33999
|
+
const page = paginate(mapped, {
|
|
34000
|
+
limit: parsePageLimit(limit, DEFAULT_MCP_LIMIT, { max: 100 }),
|
|
34001
|
+
offset: parsePageOffset(offset)
|
|
34002
|
+
});
|
|
34003
|
+
return mcpJson({
|
|
34004
|
+
skills: page.items,
|
|
34005
|
+
total: page.total,
|
|
34006
|
+
offset: page.offset,
|
|
34007
|
+
limit: page.limit,
|
|
34008
|
+
nextOffset: page.nextOffset,
|
|
34009
|
+
hasMore: page.hasMore,
|
|
34010
|
+
nextArguments: page.hasMore ? { profile: selectedProfile, category, detail: Boolean(detail), limit: page.limit, offset: page.nextOffset } : null,
|
|
34011
|
+
detailHint: detail ? undefined : "Set detail:true for full public skill objects, or call get_skill_info for one skill."
|
|
34012
|
+
});
|
|
33848
34013
|
});
|
|
33849
34014
|
server.registerTool("list_pinned_skills", {
|
|
33850
34015
|
title: "List Pinned Skills",
|
|
@@ -33861,7 +34026,7 @@ function registerDiscoveryTools(server) {
|
|
|
33861
34026
|
});
|
|
33862
34027
|
server.registerTool("search_skills", {
|
|
33863
34028
|
title: "Search Skills",
|
|
33864
|
-
description: "Search skills by name, description, or tags. Defaults to the
|
|
34029
|
+
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.",
|
|
33865
34030
|
inputSchema: {
|
|
33866
34031
|
query: exports_external.string(),
|
|
33867
34032
|
profile: exports_external.enum(["basic", "all"]).optional(),
|
|
@@ -33877,16 +34042,20 @@ function registerDiscoveryTools(server) {
|
|
|
33877
34042
|
if (!cached2)
|
|
33878
34043
|
cacheSet(cacheKey, results);
|
|
33879
34044
|
const out = detail ? results.map(getPublicSkillDiscovery) : results.map(getCompactSkillDiscovery);
|
|
33880
|
-
|
|
33881
|
-
|
|
33882
|
-
|
|
33883
|
-
|
|
33884
|
-
|
|
33885
|
-
|
|
33886
|
-
|
|
33887
|
-
|
|
33888
|
-
|
|
33889
|
-
|
|
34045
|
+
const page = paginate(out, {
|
|
34046
|
+
limit: parsePageLimit(limit, DEFAULT_MCP_LIMIT, { max: 100 }),
|
|
34047
|
+
offset: parsePageOffset(offset)
|
|
34048
|
+
});
|
|
34049
|
+
return mcpJson({
|
|
34050
|
+
skills: page.items,
|
|
34051
|
+
total: page.total,
|
|
34052
|
+
offset: page.offset,
|
|
34053
|
+
limit: page.limit,
|
|
34054
|
+
nextOffset: page.nextOffset,
|
|
34055
|
+
hasMore: page.hasMore,
|
|
34056
|
+
nextArguments: page.hasMore ? { query, profile: selectedProfile, detail: Boolean(detail), limit: page.limit, offset: page.nextOffset } : null,
|
|
34057
|
+
detailHint: detail ? undefined : "Set detail:true for full public skill objects, or call get_skill_info for one skill."
|
|
34058
|
+
});
|
|
33890
34059
|
});
|
|
33891
34060
|
server.registerTool("get_skill_info", {
|
|
33892
34061
|
title: "Get Skill Info",
|
|
@@ -34327,9 +34496,10 @@ function registerOperationTools(server) {
|
|
|
34327
34496
|
name: exports_external.string(),
|
|
34328
34497
|
input: exports_external.record(exports_external.string(), exports_external.unknown()).optional(),
|
|
34329
34498
|
args: exports_external.array(exports_external.string()).optional(),
|
|
34330
|
-
approved: exports_external.boolean().optional()
|
|
34499
|
+
approved: exports_external.boolean().optional(),
|
|
34500
|
+
detail: exports_external.boolean().optional()
|
|
34331
34501
|
}
|
|
34332
|
-
}, async ({ name, input, args, approved }) => {
|
|
34502
|
+
}, async ({ name, input, args, approved, detail }) => {
|
|
34333
34503
|
const skill = getSkill(name);
|
|
34334
34504
|
if (!skill) {
|
|
34335
34505
|
return mcpError("SKILL_NOT_FOUND", `Skill '${name}' not found`, findSimilarSkills(name));
|
|
@@ -34395,7 +34565,7 @@ function registerOperationTools(server) {
|
|
|
34395
34565
|
});
|
|
34396
34566
|
writeRunLogs(runContext, "", "");
|
|
34397
34567
|
const remoteRunId = typeof run.id === "string" ? run.id : undefined;
|
|
34398
|
-
|
|
34568
|
+
const payload2 = {
|
|
34399
34569
|
contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
|
|
34400
34570
|
id: run.id,
|
|
34401
34571
|
localRunId: localRun2.id,
|
|
@@ -34406,7 +34576,8 @@ function registerOperationTools(server) {
|
|
|
34406
34576
|
remoteRun: run,
|
|
34407
34577
|
run: localRun2,
|
|
34408
34578
|
nextActions: remoteRunNextActions(remoteRunId)
|
|
34409
|
-
}
|
|
34579
|
+
};
|
|
34580
|
+
return mcpJson(detail ? payload2 : compactRunToolPayload(payload2, "Call run_skill again with detail:true for full remote/local run records."));
|
|
34410
34581
|
} catch (err) {
|
|
34411
34582
|
const error48 = `Hosted skill ${skillName} requires hosted access: ${err.message}`;
|
|
34412
34583
|
writeRunLogs(runContext, "", error48 + `
|
|
@@ -34428,23 +34599,23 @@ function registerOperationTools(server) {
|
|
|
34428
34599
|
status: result.exitCode === 0 ? "completed" : "failed",
|
|
34429
34600
|
error: result.error
|
|
34430
34601
|
});
|
|
34602
|
+
const payload = { exitCode: result.exitCode, skill: skillName, stdout: result.stdout, stderr: result.stderr, run: localRun };
|
|
34431
34603
|
if (result.error) {
|
|
34432
34604
|
return {
|
|
34433
|
-
content: [{ type: "text", text: JSON.stringify({
|
|
34605
|
+
content: [{ type: "text", text: JSON.stringify(detail ? { ...payload, error: result.error } : compactRunToolPayload({ ...payload, error: result.error }, "Call run_skill again with detail:true for full stdout/stderr and run metadata.")) }],
|
|
34434
34606
|
isError: true
|
|
34435
34607
|
};
|
|
34436
34608
|
}
|
|
34437
|
-
return
|
|
34438
|
-
content: [{ type: "text", text: JSON.stringify({ exitCode: result.exitCode, skill: skillName, stdout: result.stdout, stderr: result.stderr, run: localRun }, null, 2) }]
|
|
34439
|
-
};
|
|
34609
|
+
return mcpJson(detail ? payload : compactRunToolPayload(payload, "Call run_skill again with detail:true for full stdout/stderr and run metadata."));
|
|
34440
34610
|
});
|
|
34441
34611
|
server.registerTool("get_run_status", {
|
|
34442
34612
|
title: "Get Run Status",
|
|
34443
34613
|
description: "Fetch remote run status. Accepts a remote run id or a local run id linked to a remote run.",
|
|
34444
34614
|
inputSchema: {
|
|
34445
|
-
run_id: exports_external.string()
|
|
34615
|
+
run_id: exports_external.string(),
|
|
34616
|
+
detail: exports_external.boolean().optional()
|
|
34446
34617
|
}
|
|
34447
|
-
}, async ({ run_id }) => {
|
|
34618
|
+
}, async ({ run_id, detail }) => {
|
|
34448
34619
|
const { getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_auth_store(), exports_auth_store));
|
|
34449
34620
|
const apiKey = getApiKey2();
|
|
34450
34621
|
if (!apiKey) {
|
|
@@ -34461,12 +34632,20 @@ function registerOperationTools(server) {
|
|
|
34461
34632
|
const run = await client.getRun(remoteRunId);
|
|
34462
34633
|
if (!run)
|
|
34463
34634
|
return mcpError("RUN_NOT_FOUND", `Remote run '${remoteRunId}' not found`);
|
|
34464
|
-
|
|
34635
|
+
const payload = {
|
|
34465
34636
|
contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
|
|
34466
34637
|
runId: remoteRunId,
|
|
34467
34638
|
...localRun ? { localRunId: localRun.id } : {},
|
|
34468
34639
|
run,
|
|
34469
34640
|
nextActions: remoteRunNextActions(remoteRunId)
|
|
34641
|
+
};
|
|
34642
|
+
return mcpJson(detail ? payload : {
|
|
34643
|
+
contractVersion: payload.contractVersion,
|
|
34644
|
+
runId: payload.runId,
|
|
34645
|
+
...localRun ? { localRunId: localRun.id } : {},
|
|
34646
|
+
run: compactRemoteRun(run),
|
|
34647
|
+
nextActions: payload.nextActions,
|
|
34648
|
+
detailHint: "Call get_run_status with detail:true for the complete remote run payload."
|
|
34470
34649
|
});
|
|
34471
34650
|
} catch (err) {
|
|
34472
34651
|
return mcpError("SKILLS_MD_ERROR", err.message);
|
|
@@ -34558,6 +34737,32 @@ function registerOperationTools(server) {
|
|
|
34558
34737
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
34559
34738
|
});
|
|
34560
34739
|
}
|
|
34740
|
+
function compactRunToolPayload(payload, detailHint) {
|
|
34741
|
+
const stdout = previewText(payload.stdout ?? "");
|
|
34742
|
+
const stderr = previewText(payload.stderr ?? "");
|
|
34743
|
+
return {
|
|
34744
|
+
...payload.contractVersion !== undefined ? { contractVersion: payload.contractVersion } : {},
|
|
34745
|
+
...payload.id !== undefined ? { id: payload.id } : {},
|
|
34746
|
+
...payload.localRunId !== undefined ? { localRunId: payload.localRunId } : {},
|
|
34747
|
+
...payload.exitCode !== undefined ? { exitCode: payload.exitCode } : {},
|
|
34748
|
+
skill: payload.skill,
|
|
34749
|
+
...payload.status !== undefined ? { status: payload.status } : {},
|
|
34750
|
+
...payload.remote !== undefined ? { remote: payload.remote } : {},
|
|
34751
|
+
...payload.correlationId !== undefined ? { correlationId: payload.correlationId } : {},
|
|
34752
|
+
...payload.pricing !== undefined ? { pricing: payload.pricing } : {},
|
|
34753
|
+
...payload.error !== undefined ? { error: payload.error } : {},
|
|
34754
|
+
...payload.remoteRun !== undefined ? { remoteRun: compactRemoteRun(payload.remoteRun) } : {},
|
|
34755
|
+
run: compactRunRecord(payload.run),
|
|
34756
|
+
stdoutPreview: stdout,
|
|
34757
|
+
stderrPreview: stderr,
|
|
34758
|
+
stdoutChars: stdout.length,
|
|
34759
|
+
stderrChars: stderr.length,
|
|
34760
|
+
stdoutTruncated: stdout.truncated,
|
|
34761
|
+
stderrTruncated: stderr.truncated,
|
|
34762
|
+
...payload.nextActions !== undefined ? { nextActions: payload.nextActions } : {},
|
|
34763
|
+
detailHint
|
|
34764
|
+
};
|
|
34765
|
+
}
|
|
34561
34766
|
|
|
34562
34767
|
// src/lib/feedback.ts
|
|
34563
34768
|
import { existsSync as existsSync11, mkdirSync as mkdirSync6 } from "fs";
|
|
@@ -34916,11 +35121,37 @@ function registerScheduleTools(server) {
|
|
|
34916
35121
|
});
|
|
34917
35122
|
server.registerTool("list_schedules", {
|
|
34918
35123
|
title: "List Schedules",
|
|
34919
|
-
description: "List
|
|
34920
|
-
inputSchema: {
|
|
34921
|
-
|
|
35124
|
+
description: "List scheduled skill runs as a compact paged response. Use limit/offset for pagination.",
|
|
35125
|
+
inputSchema: {
|
|
35126
|
+
limit: exports_external.number().optional(),
|
|
35127
|
+
offset: exports_external.number().optional()
|
|
35128
|
+
}
|
|
35129
|
+
}, async ({ limit, offset }) => {
|
|
34922
35130
|
const schedules = listSchedules();
|
|
34923
|
-
|
|
35131
|
+
const page = paginate(schedules, {
|
|
35132
|
+
limit: parsePageLimit(limit, DEFAULT_MCP_LIMIT, { max: 100 }),
|
|
35133
|
+
offset: parsePageOffset(offset)
|
|
35134
|
+
});
|
|
35135
|
+
return mcpJson({
|
|
35136
|
+
schedules: page.items.map((schedule) => ({
|
|
35137
|
+
id: schedule.id,
|
|
35138
|
+
name: schedule.name,
|
|
35139
|
+
skill: schedule.skill,
|
|
35140
|
+
cron: schedule.cron,
|
|
35141
|
+
enabled: schedule.enabled,
|
|
35142
|
+
lastRun: schedule.lastRun,
|
|
35143
|
+
lastRunStatus: schedule.lastRunStatus,
|
|
35144
|
+
nextRun: schedule.nextRun,
|
|
35145
|
+
argCount: schedule.args?.length ?? 0
|
|
35146
|
+
})),
|
|
35147
|
+
total: page.total,
|
|
35148
|
+
offset: page.offset,
|
|
35149
|
+
limit: page.limit,
|
|
35150
|
+
nextOffset: page.nextOffset,
|
|
35151
|
+
hasMore: page.hasMore,
|
|
35152
|
+
nextArguments: page.hasMore ? { limit: page.limit, offset: page.nextOffset } : null,
|
|
35153
|
+
detailHint: "Use schedule state files or future schedule detail commands for complete schedule records."
|
|
35154
|
+
});
|
|
34924
35155
|
});
|
|
34925
35156
|
server.registerTool("remove_schedule", {
|
|
34926
35157
|
title: "Remove Schedule",
|