@hasna/skills 0.1.46 → 0.1.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/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: ["whisper"], description: "Audio/video transcription with timestamps" },
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.46",
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.3",
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",
@@ -31601,9 +31602,9 @@ var MEDIA_PROCESSING_SKILLS = [
31601
31602
  {
31602
31603
  name: "transcript",
31603
31604
  displayName: "Transcript",
31604
- description: "Generate transcripts from audio and video files with timestamps",
31605
+ description: "Transcribe audio, video, and media URLs with OpenAI GPT-4o, ElevenLabs Scribe v2, DeepGram, or hosted runtime",
31605
31606
  category: "Media Processing",
31606
- tags: ["transcript", "audio", "video", "speech-to-text"]
31607
+ tags: ["transcript", "audio", "video", "speech-to-text", "diarization", "youtube"]
31607
31608
  },
31608
31609
  {
31609
31610
  name: "video-cut-suggester",
@@ -33047,18 +33048,29 @@ var runOutputSchema = objectSchema({
33047
33048
  exitCode: { type: "number", description: "Process exit code for local runs." },
33048
33049
  skill: stringSchema("Canonical skill slug."),
33049
33050
  remote: { type: "boolean", description: "Whether the skill was submitted to the hosted runtime." },
33050
- stdout: stringSchema("Captured stdout for local runs."),
33051
- stderr: stringSchema("Captured stderr for local runs."),
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."),
33052
33063
  id: stringSchema("Remote run id when submitted remotely."),
33053
33064
  localRunId: stringSchema("Local run metadata id."),
33054
33065
  status: stringSchema("Run lifecycle status."),
33055
33066
  pricing: pricingSchema,
33056
- remoteRun: objectSchema({}, [], "Normalized hosted remote run contract.", true),
33057
- run: objectSchema({}, [], "Local run metadata.", true),
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),
33058
33069
  nextActions: objectSchema({
33059
33070
  poll: stringSchema("Command to poll run status."),
33060
33071
  download: stringSchema("Command to download artifacts.")
33061
- })
33072
+ }),
33073
+ detailHint: stringSchema("How to request the complete payload.")
33062
33074
  }, [], "Skill run result.");
33063
33075
  var toolContracts = [
33064
33076
  {
@@ -33106,7 +33118,7 @@ var toolContracts = [
33106
33118
  {
33107
33119
  name: "list_skills",
33108
33120
  title: "List Skills",
33109
- 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.",
33110
33122
  params: ["category?", "profile?", "detail?", "limit?", "offset?"],
33111
33123
  category: "discovery",
33112
33124
  sideEffects: "none",
@@ -33122,7 +33134,11 @@ var toolContracts = [
33122
33134
  skills: arraySchema(skillSummarySchema),
33123
33135
  total: { type: "number" },
33124
33136
  offset: { type: "number" },
33125
- 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.")
33126
33142
  })
33127
33143
  },
33128
33144
  {
@@ -33143,7 +33159,7 @@ var toolContracts = [
33143
33159
  {
33144
33160
  name: "search_skills",
33145
33161
  title: "Search Skills",
33146
- description: "Search skills by name, description, or tags.",
33162
+ description: "Search skills by name, description, or tags. Returns a compact paged envelope by default.",
33147
33163
  params: ["query", "profile?", "detail?", "limit?", "offset?"],
33148
33164
  category: "discovery",
33149
33165
  sideEffects: "none",
@@ -33155,7 +33171,16 @@ var toolContracts = [
33155
33171
  limit: { type: "number", minimum: 0 },
33156
33172
  offset: { type: "number", minimum: 0 }
33157
33173
  }, ["query"]),
33158
- outputSchema: objectSchema({ skills: arraySchema(skillSummarySchema) })
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
+ })
33159
33184
  },
33160
33185
  {
33161
33186
  name: "get_skill_info",
@@ -33272,8 +33297,8 @@ var toolContracts = [
33272
33297
  {
33273
33298
  name: "run_skill",
33274
33299
  title: "Run Skill",
33275
- description: "Run a skill locally or through a configured remote runner.",
33276
- 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?"],
33277
33302
  category: "execution",
33278
33303
  sideEffects: "local-process-or-remote-run",
33279
33304
  stable: true,
@@ -33281,28 +33306,33 @@ var toolContracts = [
33281
33306
  name: skillNameInput,
33282
33307
  input: runInputSchema,
33283
33308
  args: runArgsSchema,
33284
- approved: paidRunApprovalSchema
33309
+ approved: paidRunApprovalSchema,
33310
+ detail: { type: "boolean", default: false, description: "Return full stdout/stderr, remote run, and local run metadata." }
33285
33311
  }, ["name"]),
33286
33312
  outputSchema: runOutputSchema
33287
33313
  },
33288
33314
  {
33289
33315
  name: "get_run_status",
33290
33316
  title: "Get Run Status",
33291
- description: "Fetch remote run status and next actions.",
33292
- 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?"],
33293
33319
  category: "execution",
33294
33320
  sideEffects: "none",
33295
33321
  stable: true,
33296
- inputSchema: objectSchema({ run_id: stringSchema("Remote or local run id.") }, ["run_id"]),
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"]),
33297
33326
  outputSchema: objectSchema({
33298
33327
  contractVersion: { type: "number", description: "Remote run payload contract version." },
33299
33328
  runId: stringSchema("Remote run id."),
33300
33329
  localRunId: stringSchema("Local run id."),
33301
- run: objectSchema({}, [], "Normalized remote run status.", true),
33330
+ run: objectSchema({}, [], "Compact remote run status by default; full status when detail:true is requested.", true),
33302
33331
  nextActions: objectSchema({
33303
33332
  poll: stringSchema("Command to poll run status."),
33304
33333
  download: stringSchema("Command to download artifacts.")
33305
- })
33334
+ }),
33335
+ detailHint: stringSchema("How to request the complete payload.")
33306
33336
  })
33307
33337
  },
33308
33338
  {
@@ -33397,13 +33427,25 @@ var toolContracts = [
33397
33427
  {
33398
33428
  name: "list_schedules",
33399
33429
  title: "List Schedules",
33400
- description: "List scheduled skill runs.",
33401
- params: [],
33430
+ description: "List scheduled skill runs as a compact paged envelope.",
33431
+ params: ["limit?", "offset?"],
33402
33432
  category: "scheduling",
33403
33433
  sideEffects: "none",
33404
33434
  stable: true,
33405
- inputSchema: objectSchema(),
33406
- outputSchema: arraySchema(objectSchema({}, [], "Schedule record.", true))
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
+ })
33407
33449
  },
33408
33450
  {
33409
33451
  name: "remove_schedule",
@@ -33810,6 +33852,90 @@ function resolveDiscoveryPricing(skill) {
33810
33852
  return skill.pricing && typeof skill.pricing.formattedCost === "string" ? skill.pricing : getPublicSkillPricing(skill.name);
33811
33853
  }
33812
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
+
33813
33939
  // src/mcp/helpers.ts
33814
33940
  function stripNulls(obj) {
33815
33941
  return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== null && v !== undefined && !(Array.isArray(v) && v.length === 0)));
@@ -33858,7 +33984,7 @@ var TOOL_DESCRIPTIONS = getMcpToolDescriptions();
33858
33984
  function registerDiscoveryTools(server) {
33859
33985
  server.registerTool("list_skills", {
33860
33986
  title: "List Skills",
33861
- description: "List skills with public pricing. Defaults to the clean basic profile to avoid context overflow. Set profile:'all' for the full registry. Returns {name,category,pricing} by default; detail:true for full public objects. Supports limit/offset pagination.",
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.",
33862
33988
  inputSchema: {
33863
33989
  category: exports_external.string().optional(),
33864
33990
  profile: exports_external.enum(["basic", "all"]).optional(),
@@ -33870,16 +33996,20 @@ function registerDiscoveryTools(server) {
33870
33996
  const selectedProfile = profile || "basic";
33871
33997
  const skills = category ? loadRegistryProfile(selectedProfile).filter((s) => s.category === category) : loadRegistryProfile(selectedProfile);
33872
33998
  const mapped = detail ? skills.map(getPublicSkillDiscovery) : skills.map(getCompactSkillDiscovery);
33873
- if (limit !== undefined || offset !== undefined) {
33874
- const start = offset || 0;
33875
- const sliced = limit !== undefined ? mapped.slice(start, start + limit) : mapped.slice(start);
33876
- return {
33877
- content: [{ type: "text", text: JSON.stringify({ skills: sliced, total: mapped.length, offset: start, limit: limit ?? null }) }]
33878
- };
33879
- }
33880
- return {
33881
- content: [{ type: "text", text: JSON.stringify(mapped) }]
33882
- };
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
+ });
33883
34013
  });
33884
34014
  server.registerTool("list_pinned_skills", {
33885
34015
  title: "List Pinned Skills",
@@ -33896,7 +34026,7 @@ function registerDiscoveryTools(server) {
33896
34026
  });
33897
34027
  server.registerTool("search_skills", {
33898
34028
  title: "Search Skills",
33899
- description: "Search skills by name, description, or tags. Defaults to the clean basic profile; set profile:'all' for the full registry. Returns compact list with pricing by default. Supports limit/offset pagination.",
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.",
33900
34030
  inputSchema: {
33901
34031
  query: exports_external.string(),
33902
34032
  profile: exports_external.enum(["basic", "all"]).optional(),
@@ -33912,16 +34042,20 @@ function registerDiscoveryTools(server) {
33912
34042
  if (!cached2)
33913
34043
  cacheSet(cacheKey, results);
33914
34044
  const out = detail ? results.map(getPublicSkillDiscovery) : results.map(getCompactSkillDiscovery);
33915
- if (limit !== undefined || offset !== undefined) {
33916
- const start = offset || 0;
33917
- const sliced = limit !== undefined ? out.slice(start, start + limit) : out.slice(start);
33918
- return {
33919
- content: [{ type: "text", text: JSON.stringify({ skills: sliced, total: out.length, offset: start, limit: limit ?? null }) }]
33920
- };
33921
- }
33922
- return {
33923
- content: [{ type: "text", text: JSON.stringify(out) }]
33924
- };
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
+ });
33925
34059
  });
33926
34060
  server.registerTool("get_skill_info", {
33927
34061
  title: "Get Skill Info",
@@ -34362,9 +34496,10 @@ function registerOperationTools(server) {
34362
34496
  name: exports_external.string(),
34363
34497
  input: exports_external.record(exports_external.string(), exports_external.unknown()).optional(),
34364
34498
  args: exports_external.array(exports_external.string()).optional(),
34365
- approved: exports_external.boolean().optional()
34499
+ approved: exports_external.boolean().optional(),
34500
+ detail: exports_external.boolean().optional()
34366
34501
  }
34367
- }, async ({ name, input, args, approved }) => {
34502
+ }, async ({ name, input, args, approved, detail }) => {
34368
34503
  const skill = getSkill(name);
34369
34504
  if (!skill) {
34370
34505
  return mcpError("SKILL_NOT_FOUND", `Skill '${name}' not found`, findSimilarSkills(name));
@@ -34430,7 +34565,7 @@ function registerOperationTools(server) {
34430
34565
  });
34431
34566
  writeRunLogs(runContext, "", "");
34432
34567
  const remoteRunId = typeof run.id === "string" ? run.id : undefined;
34433
- return mcpJson({
34568
+ const payload2 = {
34434
34569
  contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
34435
34570
  id: run.id,
34436
34571
  localRunId: localRun2.id,
@@ -34441,7 +34576,8 @@ function registerOperationTools(server) {
34441
34576
  remoteRun: run,
34442
34577
  run: localRun2,
34443
34578
  nextActions: remoteRunNextActions(remoteRunId)
34444
- });
34579
+ };
34580
+ return mcpJson(detail ? payload2 : compactRunToolPayload(payload2, "Call run_skill again with detail:true for full remote/local run records."));
34445
34581
  } catch (err) {
34446
34582
  const error48 = `Hosted skill ${skillName} requires hosted access: ${err.message}`;
34447
34583
  writeRunLogs(runContext, "", error48 + `
@@ -34463,23 +34599,23 @@ function registerOperationTools(server) {
34463
34599
  status: result.exitCode === 0 ? "completed" : "failed",
34464
34600
  error: result.error
34465
34601
  });
34602
+ const payload = { exitCode: result.exitCode, skill: skillName, stdout: result.stdout, stderr: result.stderr, run: localRun };
34466
34603
  if (result.error) {
34467
34604
  return {
34468
- content: [{ type: "text", text: JSON.stringify({ exitCode: result.exitCode, error: result.error, run: localRun }, null, 2) }],
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.")) }],
34469
34606
  isError: true
34470
34607
  };
34471
34608
  }
34472
- return {
34473
- content: [{ type: "text", text: JSON.stringify({ exitCode: result.exitCode, skill: skillName, stdout: result.stdout, stderr: result.stderr, run: localRun }, null, 2) }]
34474
- };
34609
+ return mcpJson(detail ? payload : compactRunToolPayload(payload, "Call run_skill again with detail:true for full stdout/stderr and run metadata."));
34475
34610
  });
34476
34611
  server.registerTool("get_run_status", {
34477
34612
  title: "Get Run Status",
34478
34613
  description: "Fetch remote run status. Accepts a remote run id or a local run id linked to a remote run.",
34479
34614
  inputSchema: {
34480
- run_id: exports_external.string()
34615
+ run_id: exports_external.string(),
34616
+ detail: exports_external.boolean().optional()
34481
34617
  }
34482
- }, async ({ run_id }) => {
34618
+ }, async ({ run_id, detail }) => {
34483
34619
  const { getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_auth_store(), exports_auth_store));
34484
34620
  const apiKey = getApiKey2();
34485
34621
  if (!apiKey) {
@@ -34496,12 +34632,20 @@ function registerOperationTools(server) {
34496
34632
  const run = await client.getRun(remoteRunId);
34497
34633
  if (!run)
34498
34634
  return mcpError("RUN_NOT_FOUND", `Remote run '${remoteRunId}' not found`);
34499
- return mcpJson({
34635
+ const payload = {
34500
34636
  contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
34501
34637
  runId: remoteRunId,
34502
34638
  ...localRun ? { localRunId: localRun.id } : {},
34503
34639
  run,
34504
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."
34505
34649
  });
34506
34650
  } catch (err) {
34507
34651
  return mcpError("SKILLS_MD_ERROR", err.message);
@@ -34593,6 +34737,32 @@ function registerOperationTools(server) {
34593
34737
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
34594
34738
  });
34595
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
+ }
34596
34766
 
34597
34767
  // src/lib/feedback.ts
34598
34768
  import { existsSync as existsSync11, mkdirSync as mkdirSync6 } from "fs";
@@ -34951,11 +35121,37 @@ function registerScheduleTools(server) {
34951
35121
  });
34952
35122
  server.registerTool("list_schedules", {
34953
35123
  title: "List Schedules",
34954
- description: "List all scheduled skill runs.",
34955
- inputSchema: {}
34956
- }, async () => {
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 }) => {
34957
35130
  const schedules = listSchedules();
34958
- return { content: [{ type: "text", text: JSON.stringify(schedules, null, 2) }] };
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
+ });
34959
35155
  });
34960
35156
  server.registerTool("remove_schedule", {
34961
35157
  title: "Remove Schedule",