llmist 16.1.0 → 16.2.0
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/dist/index.cjs +796 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +482 -1
- package/dist/index.d.ts +482 -1
- package/dist/index.js +776 -31
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -2,6 +2,12 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
4
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
6
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
7
|
+
}) : x)(function(x) {
|
|
8
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
9
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
10
|
+
});
|
|
5
11
|
var __esm = (fn, res) => function __init() {
|
|
6
12
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
7
13
|
};
|
|
@@ -347,15 +353,15 @@ var init_execution_tree = __esm({
|
|
|
347
353
|
const parentId = params.parentId ?? this.parentNodeId;
|
|
348
354
|
const parent = parentId ? this.nodes.get(parentId) : null;
|
|
349
355
|
const depth = parent ? parent.depth + 1 : this.baseDepth;
|
|
350
|
-
const
|
|
356
|
+
const path3 = parent ? [...parent.path] : [];
|
|
351
357
|
const id = this.generateLLMCallId(params.iteration, parentId);
|
|
352
|
-
|
|
358
|
+
path3.push(id);
|
|
353
359
|
const node = {
|
|
354
360
|
id,
|
|
355
361
|
type: "llm_call",
|
|
356
362
|
parentId,
|
|
357
363
|
depth,
|
|
358
|
-
path,
|
|
364
|
+
path: path3,
|
|
359
365
|
createdAt: Date.now(),
|
|
360
366
|
completedAt: null,
|
|
361
367
|
iteration: params.iteration,
|
|
@@ -466,15 +472,15 @@ var init_execution_tree = __esm({
|
|
|
466
472
|
const parentId = params.parentId ?? this.getCurrentLLMCallId() ?? this.parentNodeId;
|
|
467
473
|
const parent = parentId ? this.nodes.get(parentId) : null;
|
|
468
474
|
const depth = parent ? parent.depth + 1 : this.baseDepth;
|
|
469
|
-
const
|
|
475
|
+
const path3 = parent ? [...parent.path] : [];
|
|
470
476
|
const id = this.generateGadgetId(params.invocationId);
|
|
471
|
-
|
|
477
|
+
path3.push(id);
|
|
472
478
|
const node = {
|
|
473
479
|
id,
|
|
474
480
|
type: "gadget",
|
|
475
481
|
parentId,
|
|
476
482
|
depth,
|
|
477
|
-
path,
|
|
483
|
+
path: path3,
|
|
478
484
|
createdAt: Date.now(),
|
|
479
485
|
completedAt: null,
|
|
480
486
|
invocationId: params.invocationId,
|
|
@@ -1413,8 +1419,8 @@ ${this.endPrefix}`
|
|
|
1413
1419
|
});
|
|
1414
1420
|
if (media && media.length > 0 && mediaIds && mediaIds.length > 0) {
|
|
1415
1421
|
const idRefs = media.map((m, i) => {
|
|
1416
|
-
const
|
|
1417
|
-
const pathInfo =
|
|
1422
|
+
const path3 = storedMedia?.[i]?.path;
|
|
1423
|
+
const pathInfo = path3 ? ` \u2192 saved to: ${path3}` : "";
|
|
1418
1424
|
return `[Media: ${mediaIds[i]} (${m.kind})${pathInfo}]`;
|
|
1419
1425
|
}).join("\n");
|
|
1420
1426
|
const textWithIds = `Result (${invocationId}): ${result}
|
|
@@ -4022,29 +4028,29 @@ function schemaToJSONSchema(schema, options) {
|
|
|
4022
4028
|
}
|
|
4023
4029
|
function detectDescriptionMismatch(schema, jsonSchema) {
|
|
4024
4030
|
const mismatches = [];
|
|
4025
|
-
function checkSchema(zodSchema, json,
|
|
4031
|
+
function checkSchema(zodSchema, json, path3) {
|
|
4026
4032
|
if (!zodSchema || typeof zodSchema !== "object") return;
|
|
4027
4033
|
const def = zodSchema._def;
|
|
4028
4034
|
const jsonObj = json;
|
|
4029
4035
|
if (def?.description && !jsonObj?.description) {
|
|
4030
|
-
mismatches.push(
|
|
4036
|
+
mismatches.push(path3 || "root");
|
|
4031
4037
|
}
|
|
4032
4038
|
if (def?.typeName === "ZodObject" && def?.shape) {
|
|
4033
4039
|
const shape = typeof def.shape === "function" ? def.shape() : def.shape;
|
|
4034
4040
|
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
4035
4041
|
const properties = jsonObj?.properties;
|
|
4036
4042
|
const jsonProp = properties?.[key];
|
|
4037
|
-
checkSchema(fieldSchema, jsonProp,
|
|
4043
|
+
checkSchema(fieldSchema, jsonProp, path3 ? `${path3}.${key}` : key);
|
|
4038
4044
|
}
|
|
4039
4045
|
}
|
|
4040
4046
|
if (def?.typeName === "ZodArray" && def?.type) {
|
|
4041
|
-
checkSchema(def.type, jsonObj?.items,
|
|
4047
|
+
checkSchema(def.type, jsonObj?.items, path3 ? `${path3}[]` : "[]");
|
|
4042
4048
|
}
|
|
4043
4049
|
if ((def?.typeName === "ZodOptional" || def?.typeName === "ZodNullable") && def?.innerType) {
|
|
4044
|
-
checkSchema(def.innerType, json,
|
|
4050
|
+
checkSchema(def.innerType, json, path3);
|
|
4045
4051
|
}
|
|
4046
4052
|
if (def?.typeName === "ZodDefault" && def?.innerType) {
|
|
4047
|
-
checkSchema(def.innerType, json,
|
|
4053
|
+
checkSchema(def.innerType, json, path3);
|
|
4048
4054
|
}
|
|
4049
4055
|
}
|
|
4050
4056
|
checkSchema(schema, jsonSchema, "");
|
|
@@ -4136,7 +4142,7 @@ Example fixes:
|
|
|
4136
4142
|
);
|
|
4137
4143
|
}
|
|
4138
4144
|
}
|
|
4139
|
-
function findUnknownTypes(schema,
|
|
4145
|
+
function findUnknownTypes(schema, path3 = []) {
|
|
4140
4146
|
const issues = [];
|
|
4141
4147
|
if (!schema || typeof schema !== "object") {
|
|
4142
4148
|
return issues;
|
|
@@ -4148,7 +4154,7 @@ function findUnknownTypes(schema, path = []) {
|
|
|
4148
4154
|
}
|
|
4149
4155
|
if (schema.properties) {
|
|
4150
4156
|
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
4151
|
-
const propPath = [...
|
|
4157
|
+
const propPath = [...path3, propName];
|
|
4152
4158
|
if (hasNoType(propSchema)) {
|
|
4153
4159
|
issues.push(propPath.join(".") || propName);
|
|
4154
4160
|
}
|
|
@@ -4156,7 +4162,7 @@ function findUnknownTypes(schema, path = []) {
|
|
|
4156
4162
|
}
|
|
4157
4163
|
}
|
|
4158
4164
|
if (schema.items) {
|
|
4159
|
-
const itemPath = [...
|
|
4165
|
+
const itemPath = [...path3, "[]"];
|
|
4160
4166
|
if (hasNoType(schema.items)) {
|
|
4161
4167
|
issues.push(itemPath.join("."));
|
|
4162
4168
|
}
|
|
@@ -4164,17 +4170,17 @@ function findUnknownTypes(schema, path = []) {
|
|
|
4164
4170
|
}
|
|
4165
4171
|
if (schema.anyOf) {
|
|
4166
4172
|
schema.anyOf.forEach((subSchema, index) => {
|
|
4167
|
-
issues.push(...findUnknownTypes(subSchema, [...
|
|
4173
|
+
issues.push(...findUnknownTypes(subSchema, [...path3, `anyOf[${index}]`]));
|
|
4168
4174
|
});
|
|
4169
4175
|
}
|
|
4170
4176
|
if (schema.oneOf) {
|
|
4171
4177
|
schema.oneOf.forEach((subSchema, index) => {
|
|
4172
|
-
issues.push(...findUnknownTypes(subSchema, [...
|
|
4178
|
+
issues.push(...findUnknownTypes(subSchema, [...path3, `oneOf[${index}]`]));
|
|
4173
4179
|
});
|
|
4174
4180
|
}
|
|
4175
4181
|
if (schema.allOf) {
|
|
4176
4182
|
schema.allOf.forEach((subSchema, index) => {
|
|
4177
|
-
issues.push(...findUnknownTypes(subSchema, [...
|
|
4183
|
+
issues.push(...findUnknownTypes(subSchema, [...path3, `allOf[${index}]`]));
|
|
4178
4184
|
});
|
|
4179
4185
|
}
|
|
4180
4186
|
return issues;
|
|
@@ -5190,6 +5196,625 @@ var init_registry = __esm({
|
|
|
5190
5196
|
}
|
|
5191
5197
|
});
|
|
5192
5198
|
|
|
5199
|
+
// src/skills/activation.ts
|
|
5200
|
+
import { execSync } from "child_process";
|
|
5201
|
+
function substituteArguments(instructions, args) {
|
|
5202
|
+
if (!args) {
|
|
5203
|
+
return instructions.replace(/\$ARGUMENTS\[\d+\]/g, "").replace(/\$ARGUMENTS/g, "").replace(/\$\d+/g, "");
|
|
5204
|
+
}
|
|
5205
|
+
const parts = splitArguments(args);
|
|
5206
|
+
let result = instructions.replace(/\$ARGUMENTS\[(\d+)\]/g, (_match, index) => {
|
|
5207
|
+
const i = Number.parseInt(index, 10);
|
|
5208
|
+
return parts[i] ?? "";
|
|
5209
|
+
});
|
|
5210
|
+
result = result.replace(/\$ARGUMENTS/g, args);
|
|
5211
|
+
result = result.replace(/\$(\d+)/g, (_match, index) => {
|
|
5212
|
+
const i = Number.parseInt(index, 10);
|
|
5213
|
+
return parts[i] ?? "";
|
|
5214
|
+
});
|
|
5215
|
+
return result;
|
|
5216
|
+
}
|
|
5217
|
+
function preprocessShellCommands(instructions, options) {
|
|
5218
|
+
const { cwd, shell = "bash", timeoutMs = 1e4 } = options ?? {};
|
|
5219
|
+
return instructions.replace(/!`([^`]+)`/g, (_match, command) => {
|
|
5220
|
+
try {
|
|
5221
|
+
const output = execSync(command, {
|
|
5222
|
+
cwd,
|
|
5223
|
+
shell: shell === "powershell" ? "powershell" : "/bin/bash",
|
|
5224
|
+
timeout: timeoutMs,
|
|
5225
|
+
encoding: "utf-8",
|
|
5226
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
5227
|
+
});
|
|
5228
|
+
return output.trim();
|
|
5229
|
+
} catch (error) {
|
|
5230
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
5231
|
+
return `[Error executing \`${command}\`: ${msg}]`;
|
|
5232
|
+
}
|
|
5233
|
+
});
|
|
5234
|
+
}
|
|
5235
|
+
function substituteVariables(instructions, variables) {
|
|
5236
|
+
return instructions.replace(/\$\{(\w+)\}/g, (_match, varName) => {
|
|
5237
|
+
return variables[varName] ?? "";
|
|
5238
|
+
});
|
|
5239
|
+
}
|
|
5240
|
+
function resolveInstructions(instructions, options) {
|
|
5241
|
+
let resolved = instructions;
|
|
5242
|
+
if (options?.variables) {
|
|
5243
|
+
resolved = substituteVariables(resolved, options.variables);
|
|
5244
|
+
}
|
|
5245
|
+
resolved = substituteArguments(resolved, options?.arguments);
|
|
5246
|
+
if (options?.enableShellPreprocessing !== false) {
|
|
5247
|
+
resolved = preprocessShellCommands(resolved, {
|
|
5248
|
+
cwd: options?.cwd,
|
|
5249
|
+
shell: options?.shell,
|
|
5250
|
+
timeoutMs: options?.shellTimeoutMs
|
|
5251
|
+
});
|
|
5252
|
+
}
|
|
5253
|
+
return resolved;
|
|
5254
|
+
}
|
|
5255
|
+
function splitArguments(args) {
|
|
5256
|
+
const parts = [];
|
|
5257
|
+
let current = "";
|
|
5258
|
+
let inQuote = null;
|
|
5259
|
+
for (const char of args) {
|
|
5260
|
+
if (inQuote) {
|
|
5261
|
+
if (char === inQuote) {
|
|
5262
|
+
inQuote = null;
|
|
5263
|
+
} else {
|
|
5264
|
+
current += char;
|
|
5265
|
+
}
|
|
5266
|
+
} else if (char === '"' || char === "'") {
|
|
5267
|
+
inQuote = char;
|
|
5268
|
+
} else if (char === " " || char === " ") {
|
|
5269
|
+
if (current) {
|
|
5270
|
+
parts.push(current);
|
|
5271
|
+
current = "";
|
|
5272
|
+
}
|
|
5273
|
+
} else {
|
|
5274
|
+
current += char;
|
|
5275
|
+
}
|
|
5276
|
+
}
|
|
5277
|
+
if (current) parts.push(current);
|
|
5278
|
+
return parts;
|
|
5279
|
+
}
|
|
5280
|
+
var init_activation = __esm({
|
|
5281
|
+
"src/skills/activation.ts"() {
|
|
5282
|
+
"use strict";
|
|
5283
|
+
}
|
|
5284
|
+
});
|
|
5285
|
+
|
|
5286
|
+
// src/skills/parser.ts
|
|
5287
|
+
import fs from "fs";
|
|
5288
|
+
import path from "path";
|
|
5289
|
+
import yaml from "js-yaml";
|
|
5290
|
+
function parseFrontmatter(content) {
|
|
5291
|
+
const trimmed = content.trimStart();
|
|
5292
|
+
if (!trimmed.startsWith("---")) {
|
|
5293
|
+
return { frontmatter: {}, body: content };
|
|
5294
|
+
}
|
|
5295
|
+
const endIndex = trimmed.indexOf("\n---", 3);
|
|
5296
|
+
if (endIndex === -1) {
|
|
5297
|
+
return { frontmatter: {}, body: content };
|
|
5298
|
+
}
|
|
5299
|
+
const yamlBlock = trimmed.slice(3, endIndex).trim();
|
|
5300
|
+
const body = trimmed.slice(endIndex + 4).trim();
|
|
5301
|
+
const parsed = yaml.load(yamlBlock);
|
|
5302
|
+
const frontmatter = typeof parsed === "object" && parsed !== null ? parsed : {};
|
|
5303
|
+
return { frontmatter, body };
|
|
5304
|
+
}
|
|
5305
|
+
function parseMetadata(frontmatter, fallbackName) {
|
|
5306
|
+
const name = parseString(frontmatter.name) ?? fallbackName ?? "unnamed-skill";
|
|
5307
|
+
const description = parseString(frontmatter.description) ?? "";
|
|
5308
|
+
return {
|
|
5309
|
+
name,
|
|
5310
|
+
description,
|
|
5311
|
+
argumentHint: parseString(frontmatter["argument-hint"]),
|
|
5312
|
+
allowedTools: parseStringArray(frontmatter["allowed-tools"]),
|
|
5313
|
+
model: parseString(frontmatter.model),
|
|
5314
|
+
context: parseContext(frontmatter.context),
|
|
5315
|
+
agent: parseString(frontmatter.agent),
|
|
5316
|
+
paths: parseStringArray(frontmatter.paths),
|
|
5317
|
+
gadgets: parseStringArray(frontmatter.gadgets),
|
|
5318
|
+
disableModelInvocation: parseBool(frontmatter["disable-model-invocation"]),
|
|
5319
|
+
userInvocable: parseBool(frontmatter["user-invocable"]),
|
|
5320
|
+
shell: parseShell(frontmatter.shell),
|
|
5321
|
+
version: parseString(frontmatter.version)
|
|
5322
|
+
};
|
|
5323
|
+
}
|
|
5324
|
+
function scanResources(skillDir) {
|
|
5325
|
+
const resources = [];
|
|
5326
|
+
for (const category of RESOURCE_CATEGORIES) {
|
|
5327
|
+
const categoryDir = path.join(skillDir, category);
|
|
5328
|
+
if (!fs.existsSync(categoryDir)) continue;
|
|
5329
|
+
const stat = fs.statSync(categoryDir);
|
|
5330
|
+
if (!stat.isDirectory()) continue;
|
|
5331
|
+
for (const file of walkDirectory(categoryDir)) {
|
|
5332
|
+
resources.push({
|
|
5333
|
+
relativePath: path.relative(skillDir, file),
|
|
5334
|
+
absolutePath: file,
|
|
5335
|
+
category
|
|
5336
|
+
});
|
|
5337
|
+
}
|
|
5338
|
+
}
|
|
5339
|
+
return resources;
|
|
5340
|
+
}
|
|
5341
|
+
function parseSkillFile(skillMdPath, source, loadInstructions = false) {
|
|
5342
|
+
const content = fs.readFileSync(skillMdPath, "utf-8");
|
|
5343
|
+
return parseSkillContent(content, skillMdPath, source, loadInstructions);
|
|
5344
|
+
}
|
|
5345
|
+
function parseSkillContent(content, sourcePath, source, loadInstructions = false) {
|
|
5346
|
+
const sourceDir = path.dirname(sourcePath);
|
|
5347
|
+
const fallbackName = path.basename(sourceDir);
|
|
5348
|
+
const { frontmatter, body } = parseFrontmatter(content);
|
|
5349
|
+
const metadata = parseMetadata(frontmatter, fallbackName);
|
|
5350
|
+
const resources = fs.existsSync(sourceDir) ? scanResources(sourceDir) : [];
|
|
5351
|
+
return {
|
|
5352
|
+
metadata,
|
|
5353
|
+
instructions: loadInstructions ? body : null,
|
|
5354
|
+
resources,
|
|
5355
|
+
sourcePath,
|
|
5356
|
+
sourceDir,
|
|
5357
|
+
source
|
|
5358
|
+
};
|
|
5359
|
+
}
|
|
5360
|
+
function validateMetadata(metadata) {
|
|
5361
|
+
const issues = [];
|
|
5362
|
+
if (!metadata.name) {
|
|
5363
|
+
issues.push("Skill name is required");
|
|
5364
|
+
} else {
|
|
5365
|
+
if (metadata.name.length > MAX_NAME_LENGTH) {
|
|
5366
|
+
issues.push(`Skill name exceeds ${MAX_NAME_LENGTH} characters`);
|
|
5367
|
+
}
|
|
5368
|
+
if (!NAME_PATTERN.test(metadata.name)) {
|
|
5369
|
+
issues.push(
|
|
5370
|
+
"Skill name must contain only lowercase letters, numbers, and hyphens, and must start with a letter or number"
|
|
5371
|
+
);
|
|
5372
|
+
}
|
|
5373
|
+
}
|
|
5374
|
+
if (!metadata.description) {
|
|
5375
|
+
issues.push("Skill description is required");
|
|
5376
|
+
} else if (metadata.description.length > MAX_DESCRIPTION_LENGTH) {
|
|
5377
|
+
issues.push(`Skill description exceeds ${MAX_DESCRIPTION_LENGTH} characters`);
|
|
5378
|
+
}
|
|
5379
|
+
if (metadata.context && metadata.context !== "fork" && metadata.context !== "inline") {
|
|
5380
|
+
issues.push('Skill context must be "fork" or "inline"');
|
|
5381
|
+
}
|
|
5382
|
+
return issues;
|
|
5383
|
+
}
|
|
5384
|
+
function parseString(value) {
|
|
5385
|
+
if (value == null) return void 0;
|
|
5386
|
+
if (typeof value === "string") return value;
|
|
5387
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
5388
|
+
return void 0;
|
|
5389
|
+
}
|
|
5390
|
+
function parseStringArray(value) {
|
|
5391
|
+
if (value == null) return void 0;
|
|
5392
|
+
if (Array.isArray(value)) {
|
|
5393
|
+
return value.filter((v) => typeof v === "string" || typeof v === "number").map(String);
|
|
5394
|
+
}
|
|
5395
|
+
if (typeof value === "string") return [value];
|
|
5396
|
+
return void 0;
|
|
5397
|
+
}
|
|
5398
|
+
function parseContext(value) {
|
|
5399
|
+
if (value === "fork" || value === "inline") return value;
|
|
5400
|
+
return void 0;
|
|
5401
|
+
}
|
|
5402
|
+
function parseShell(value) {
|
|
5403
|
+
if (value === "bash" || value === "powershell") return value;
|
|
5404
|
+
return void 0;
|
|
5405
|
+
}
|
|
5406
|
+
function parseBool(value) {
|
|
5407
|
+
if (value === true || value === false) return value;
|
|
5408
|
+
if (value === "true") return true;
|
|
5409
|
+
if (value === "false") return false;
|
|
5410
|
+
return void 0;
|
|
5411
|
+
}
|
|
5412
|
+
function* walkDirectory(dir) {
|
|
5413
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
5414
|
+
for (const entry of entries) {
|
|
5415
|
+
const fullPath = path.join(dir, entry.name);
|
|
5416
|
+
if (entry.isDirectory()) {
|
|
5417
|
+
yield* walkDirectory(fullPath);
|
|
5418
|
+
} else if (entry.isFile()) {
|
|
5419
|
+
yield fullPath;
|
|
5420
|
+
}
|
|
5421
|
+
}
|
|
5422
|
+
}
|
|
5423
|
+
var RESOURCE_CATEGORIES, MAX_NAME_LENGTH, MAX_DESCRIPTION_LENGTH, NAME_PATTERN;
|
|
5424
|
+
var init_parser = __esm({
|
|
5425
|
+
"src/skills/parser.ts"() {
|
|
5426
|
+
"use strict";
|
|
5427
|
+
RESOURCE_CATEGORIES = ["scripts", "references", "assets"];
|
|
5428
|
+
MAX_NAME_LENGTH = 64;
|
|
5429
|
+
MAX_DESCRIPTION_LENGTH = 1024;
|
|
5430
|
+
NAME_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
5431
|
+
}
|
|
5432
|
+
});
|
|
5433
|
+
|
|
5434
|
+
// src/skills/registry.ts
|
|
5435
|
+
var registry_exports = {};
|
|
5436
|
+
__export(registry_exports, {
|
|
5437
|
+
SkillRegistry: () => SkillRegistry
|
|
5438
|
+
});
|
|
5439
|
+
import { minimatch } from "minimatch";
|
|
5440
|
+
var DEFAULT_CHAR_BUDGET, SUMMARY_DESCRIPTION_LIMIT, SkillRegistry;
|
|
5441
|
+
var init_registry2 = __esm({
|
|
5442
|
+
"src/skills/registry.ts"() {
|
|
5443
|
+
"use strict";
|
|
5444
|
+
DEFAULT_CHAR_BUDGET = 8e3;
|
|
5445
|
+
SUMMARY_DESCRIPTION_LIMIT = 250;
|
|
5446
|
+
SkillRegistry = class _SkillRegistry {
|
|
5447
|
+
skills = /* @__PURE__ */ new Map();
|
|
5448
|
+
/**
|
|
5449
|
+
* Register a skill. Overwrites any existing skill with the same name.
|
|
5450
|
+
*
|
|
5451
|
+
* Unlike GadgetRegistry (which throws on duplicates), SkillRegistry allows
|
|
5452
|
+
* overwriting because skills are loaded from multiple sources with intentional
|
|
5453
|
+
* priority ordering (project > user > default).
|
|
5454
|
+
*/
|
|
5455
|
+
register(skill) {
|
|
5456
|
+
this.skills.set(skill.name.toLowerCase(), skill);
|
|
5457
|
+
}
|
|
5458
|
+
/** Register multiple skills. */
|
|
5459
|
+
registerMany(skills) {
|
|
5460
|
+
for (const skill of skills) {
|
|
5461
|
+
this.register(skill);
|
|
5462
|
+
}
|
|
5463
|
+
}
|
|
5464
|
+
/** Remove a skill by name (case-insensitive). Returns true if removed. */
|
|
5465
|
+
remove(name) {
|
|
5466
|
+
return this.skills.delete(name.toLowerCase());
|
|
5467
|
+
}
|
|
5468
|
+
/** Remove all registered skills. */
|
|
5469
|
+
clear() {
|
|
5470
|
+
this.skills.clear();
|
|
5471
|
+
}
|
|
5472
|
+
/** Get a skill by name (case-insensitive). */
|
|
5473
|
+
get(name) {
|
|
5474
|
+
return this.skills.get(name.toLowerCase());
|
|
5475
|
+
}
|
|
5476
|
+
/** Check if a skill exists by name (case-insensitive). */
|
|
5477
|
+
has(name) {
|
|
5478
|
+
return this.skills.has(name.toLowerCase());
|
|
5479
|
+
}
|
|
5480
|
+
/** Get all registered skills. */
|
|
5481
|
+
getAll() {
|
|
5482
|
+
return [...this.skills.values()];
|
|
5483
|
+
}
|
|
5484
|
+
/** Get all skill names. */
|
|
5485
|
+
getNames() {
|
|
5486
|
+
return [...this.skills.keys()];
|
|
5487
|
+
}
|
|
5488
|
+
/** Number of registered skills. */
|
|
5489
|
+
get size() {
|
|
5490
|
+
return this.skills.size;
|
|
5491
|
+
}
|
|
5492
|
+
/**
|
|
5493
|
+
* Get skills that are visible to the LLM for auto-triggering.
|
|
5494
|
+
* Excludes skills with disableModelInvocation: true.
|
|
5495
|
+
*/
|
|
5496
|
+
getModelInvocable() {
|
|
5497
|
+
return this.getAll().filter((s) => s.isModelInvocable);
|
|
5498
|
+
}
|
|
5499
|
+
/**
|
|
5500
|
+
* Get skills that the user can invoke via /skill-name.
|
|
5501
|
+
* Excludes skills with userInvocable: false.
|
|
5502
|
+
*/
|
|
5503
|
+
getUserInvocable() {
|
|
5504
|
+
return this.getAll().filter((s) => s.isUserInvocable);
|
|
5505
|
+
}
|
|
5506
|
+
/**
|
|
5507
|
+
* Generate metadata summaries for system prompt injection (Tier 1).
|
|
5508
|
+
*
|
|
5509
|
+
* Each skill contributes a one-line summary: "name — description".
|
|
5510
|
+
* Output is truncated to fit the character budget.
|
|
5511
|
+
*
|
|
5512
|
+
* @param charBudget - Maximum characters for all summaries combined.
|
|
5513
|
+
*/
|
|
5514
|
+
getMetadataSummaries(charBudget = DEFAULT_CHAR_BUDGET) {
|
|
5515
|
+
const invocable = this.getModelInvocable();
|
|
5516
|
+
if (invocable.length === 0) return "";
|
|
5517
|
+
const lines = [];
|
|
5518
|
+
let totalChars = 0;
|
|
5519
|
+
for (const skill of invocable) {
|
|
5520
|
+
const desc = skill.description.length > SUMMARY_DESCRIPTION_LIMIT ? `${skill.description.slice(0, SUMMARY_DESCRIPTION_LIMIT - 3)}...` : skill.description;
|
|
5521
|
+
const line = `- ${skill.name}: ${desc}`;
|
|
5522
|
+
if (totalChars + line.length > charBudget) break;
|
|
5523
|
+
lines.push(line);
|
|
5524
|
+
totalChars += line.length + 1;
|
|
5525
|
+
}
|
|
5526
|
+
return lines.join("\n");
|
|
5527
|
+
}
|
|
5528
|
+
/**
|
|
5529
|
+
* Find skills whose `paths` patterns match a given file path.
|
|
5530
|
+
* Used for auto-activation when the user is working on specific files.
|
|
5531
|
+
*/
|
|
5532
|
+
findByFilePath(filePath) {
|
|
5533
|
+
return this.getModelInvocable().filter((skill) => {
|
|
5534
|
+
const patterns = skill.metadata.paths;
|
|
5535
|
+
if (!patterns || patterns.length === 0) return false;
|
|
5536
|
+
return patterns.some((pattern) => minimatch(filePath, pattern));
|
|
5537
|
+
});
|
|
5538
|
+
}
|
|
5539
|
+
/**
|
|
5540
|
+
* Merge another registry into this one.
|
|
5541
|
+
* Skills from the other registry overwrite existing skills with the same name.
|
|
5542
|
+
*/
|
|
5543
|
+
merge(other) {
|
|
5544
|
+
for (const skill of other.getAll()) {
|
|
5545
|
+
this.register(skill);
|
|
5546
|
+
}
|
|
5547
|
+
}
|
|
5548
|
+
/** Create a registry from an array of skills. */
|
|
5549
|
+
static from(skills) {
|
|
5550
|
+
const registry = new _SkillRegistry();
|
|
5551
|
+
registry.registerMany(skills);
|
|
5552
|
+
return registry;
|
|
5553
|
+
}
|
|
5554
|
+
};
|
|
5555
|
+
}
|
|
5556
|
+
});
|
|
5557
|
+
|
|
5558
|
+
// src/skills/skill.ts
|
|
5559
|
+
import fs2 from "fs/promises";
|
|
5560
|
+
var Skill;
|
|
5561
|
+
var init_skill = __esm({
|
|
5562
|
+
"src/skills/skill.ts"() {
|
|
5563
|
+
"use strict";
|
|
5564
|
+
init_activation();
|
|
5565
|
+
init_parser();
|
|
5566
|
+
Skill = class _Skill {
|
|
5567
|
+
metadata;
|
|
5568
|
+
sourcePath;
|
|
5569
|
+
sourceDir;
|
|
5570
|
+
source;
|
|
5571
|
+
_instructions;
|
|
5572
|
+
_resources;
|
|
5573
|
+
_resourceCache = /* @__PURE__ */ new Map();
|
|
5574
|
+
_resourceLoading = /* @__PURE__ */ new Map();
|
|
5575
|
+
constructor(parsed) {
|
|
5576
|
+
this.metadata = parsed.metadata;
|
|
5577
|
+
this.sourcePath = parsed.sourcePath;
|
|
5578
|
+
this.sourceDir = parsed.sourceDir;
|
|
5579
|
+
this.source = parsed.source;
|
|
5580
|
+
this._instructions = parsed.instructions;
|
|
5581
|
+
this._resources = parsed.resources;
|
|
5582
|
+
}
|
|
5583
|
+
/** Skill name for registry lookup. */
|
|
5584
|
+
get name() {
|
|
5585
|
+
return this.metadata.name;
|
|
5586
|
+
}
|
|
5587
|
+
/** Skill description for LLM matching. */
|
|
5588
|
+
get description() {
|
|
5589
|
+
return this.metadata.description;
|
|
5590
|
+
}
|
|
5591
|
+
/** Whether the LLM can auto-trigger this skill. */
|
|
5592
|
+
get isModelInvocable() {
|
|
5593
|
+
return this.metadata.disableModelInvocation !== true;
|
|
5594
|
+
}
|
|
5595
|
+
/** Whether the user can invoke this skill via /skill-name. */
|
|
5596
|
+
get isUserInvocable() {
|
|
5597
|
+
return this.metadata.userInvocable !== false;
|
|
5598
|
+
}
|
|
5599
|
+
/**
|
|
5600
|
+
* Load and cache Tier 2 instructions.
|
|
5601
|
+
* If instructions were loaded during parsing, returns the cached value.
|
|
5602
|
+
*/
|
|
5603
|
+
async getInstructions() {
|
|
5604
|
+
if (this._instructions !== null) return this._instructions;
|
|
5605
|
+
const content = await fs2.readFile(this.sourcePath, "utf-8");
|
|
5606
|
+
const { body } = parseFrontmatter(content);
|
|
5607
|
+
this._instructions = body;
|
|
5608
|
+
return body;
|
|
5609
|
+
}
|
|
5610
|
+
/**
|
|
5611
|
+
* List Tier 3 resources.
|
|
5612
|
+
* Resources are discovered at parse time but content is loaded on demand.
|
|
5613
|
+
*/
|
|
5614
|
+
getResources() {
|
|
5615
|
+
return this._resources;
|
|
5616
|
+
}
|
|
5617
|
+
/**
|
|
5618
|
+
* Load a specific Tier 3 resource by relative path.
|
|
5619
|
+
* Results are cached for the lifetime of this Skill instance.
|
|
5620
|
+
* Concurrent calls for the same resource share a single read.
|
|
5621
|
+
*/
|
|
5622
|
+
async getResource(relativePath) {
|
|
5623
|
+
if (relativePath.includes("..")) {
|
|
5624
|
+
throw new Error(`Invalid resource path (path traversal): ${relativePath}`);
|
|
5625
|
+
}
|
|
5626
|
+
const cached = this._resourceCache.get(relativePath);
|
|
5627
|
+
if (cached !== void 0) return cached;
|
|
5628
|
+
const existing = this._resourceLoading.get(relativePath);
|
|
5629
|
+
if (existing) return existing;
|
|
5630
|
+
const resource = this._resources.find((r) => r.relativePath === relativePath);
|
|
5631
|
+
if (!resource) {
|
|
5632
|
+
throw new Error(`Resource not found: ${relativePath} in skill ${this.name}`);
|
|
5633
|
+
}
|
|
5634
|
+
const loadPromise = fs2.readFile(resource.absolutePath, "utf-8").then(
|
|
5635
|
+
(content) => {
|
|
5636
|
+
this._resourceCache.set(relativePath, content);
|
|
5637
|
+
this._resourceLoading.delete(relativePath);
|
|
5638
|
+
return content;
|
|
5639
|
+
},
|
|
5640
|
+
(error) => {
|
|
5641
|
+
this._resourceLoading.delete(relativePath);
|
|
5642
|
+
throw new Error(
|
|
5643
|
+
`Failed to load resource ${relativePath} in skill ${this.name}: ${error instanceof Error ? error.message : String(error)}`
|
|
5644
|
+
);
|
|
5645
|
+
}
|
|
5646
|
+
);
|
|
5647
|
+
this._resourceLoading.set(relativePath, loadPromise);
|
|
5648
|
+
return loadPromise;
|
|
5649
|
+
}
|
|
5650
|
+
/**
|
|
5651
|
+
* Activate this skill with optional arguments.
|
|
5652
|
+
*
|
|
5653
|
+
* Performs:
|
|
5654
|
+
* 1. Variable substitution (${SKILL_DIR}, etc.)
|
|
5655
|
+
* 2. Argument substitution ($ARGUMENTS, $0, $1)
|
|
5656
|
+
* 3. Shell preprocessing (!`command`)
|
|
5657
|
+
* 4. Resource loading (if eagerResources is true)
|
|
5658
|
+
*/
|
|
5659
|
+
async activate(options) {
|
|
5660
|
+
const instructions = await this.getInstructions();
|
|
5661
|
+
const resolvedInstructions = resolveInstructions(instructions, {
|
|
5662
|
+
arguments: options?.arguments,
|
|
5663
|
+
variables: {
|
|
5664
|
+
SKILL_DIR: this.sourceDir,
|
|
5665
|
+
CLAUDE_SKILL_DIR: this.sourceDir
|
|
5666
|
+
},
|
|
5667
|
+
cwd: options?.cwd ?? this.sourceDir,
|
|
5668
|
+
shell: this.metadata.shell,
|
|
5669
|
+
enableShellPreprocessing: options?.enableShellPreprocessing,
|
|
5670
|
+
shellTimeoutMs: options?.shellTimeoutMs
|
|
5671
|
+
});
|
|
5672
|
+
const loadedResources = /* @__PURE__ */ new Map();
|
|
5673
|
+
if (options?.eagerResources) {
|
|
5674
|
+
for (const resource of this._resources) {
|
|
5675
|
+
const content = await this.getResource(resource.relativePath);
|
|
5676
|
+
loadedResources.set(resource.relativePath, content);
|
|
5677
|
+
}
|
|
5678
|
+
}
|
|
5679
|
+
return {
|
|
5680
|
+
skillName: this.name,
|
|
5681
|
+
resolvedInstructions,
|
|
5682
|
+
gadgets: [],
|
|
5683
|
+
// Gadgets are resolved by the CLI layer
|
|
5684
|
+
loadedResources
|
|
5685
|
+
};
|
|
5686
|
+
}
|
|
5687
|
+
/**
|
|
5688
|
+
* Create a Skill from a SKILL.md content string.
|
|
5689
|
+
* Useful for testing or dynamic skill creation.
|
|
5690
|
+
*/
|
|
5691
|
+
static fromContent(content, sourcePath, source = { type: "directory", path: sourcePath }) {
|
|
5692
|
+
const parsed = parseSkillContent(content, sourcePath, source, true);
|
|
5693
|
+
return new _Skill(parsed);
|
|
5694
|
+
}
|
|
5695
|
+
};
|
|
5696
|
+
}
|
|
5697
|
+
});
|
|
5698
|
+
|
|
5699
|
+
// src/skills/loader.ts
|
|
5700
|
+
import fs3 from "fs";
|
|
5701
|
+
import os from "os";
|
|
5702
|
+
import path2 from "path";
|
|
5703
|
+
function loadSkillsFromDirectory(dir, source, onWarning) {
|
|
5704
|
+
if (!fs3.existsSync(dir)) return [];
|
|
5705
|
+
const stat = fs3.statSync(dir);
|
|
5706
|
+
if (!stat.isDirectory()) return [];
|
|
5707
|
+
const skills = [];
|
|
5708
|
+
scanForSkills(dir, source, skills, onWarning);
|
|
5709
|
+
return skills;
|
|
5710
|
+
}
|
|
5711
|
+
function discoverSkills(options) {
|
|
5712
|
+
const registry = new SkillRegistry();
|
|
5713
|
+
const userSkillsDir = options?.userDir ?? path2.join(os.homedir(), CONFIG_DIR_NAME, SKILLS_DIR_NAME);
|
|
5714
|
+
const userSkills = loadSkillsFromDirectory(userSkillsDir, {
|
|
5715
|
+
type: "user",
|
|
5716
|
+
path: userSkillsDir
|
|
5717
|
+
});
|
|
5718
|
+
registry.registerMany(userSkills);
|
|
5719
|
+
if (options?.projectDir) {
|
|
5720
|
+
const projectSkillsDir = path2.join(options.projectDir, CONFIG_DIR_NAME, SKILLS_DIR_NAME);
|
|
5721
|
+
const projectSkills = loadSkillsFromDirectory(projectSkillsDir, {
|
|
5722
|
+
type: "project",
|
|
5723
|
+
path: projectSkillsDir
|
|
5724
|
+
});
|
|
5725
|
+
registry.registerMany(projectSkills);
|
|
5726
|
+
}
|
|
5727
|
+
if (options?.additionalDirs) {
|
|
5728
|
+
for (const dir of options.additionalDirs) {
|
|
5729
|
+
const resolvedDir = dir.startsWith("~") ? path2.join(os.homedir(), dir.slice(1)) : dir;
|
|
5730
|
+
const skills = loadSkillsFromDirectory(resolvedDir, {
|
|
5731
|
+
type: "directory",
|
|
5732
|
+
path: resolvedDir
|
|
5733
|
+
});
|
|
5734
|
+
registry.registerMany(skills);
|
|
5735
|
+
}
|
|
5736
|
+
}
|
|
5737
|
+
return registry;
|
|
5738
|
+
}
|
|
5739
|
+
function scanForSkills(dir, source, results, onWarning) {
|
|
5740
|
+
let entries;
|
|
5741
|
+
try {
|
|
5742
|
+
entries = fs3.readdirSync(dir, { withFileTypes: true });
|
|
5743
|
+
} catch (error) {
|
|
5744
|
+
onWarning?.(
|
|
5745
|
+
`Cannot read skill directory ${dir}: ${error instanceof Error ? error.message : String(error)}`
|
|
5746
|
+
);
|
|
5747
|
+
return;
|
|
5748
|
+
}
|
|
5749
|
+
const skillMdPath = path2.join(dir, "SKILL.md");
|
|
5750
|
+
if (fs3.existsSync(skillMdPath)) {
|
|
5751
|
+
try {
|
|
5752
|
+
const parsed = parseSkillFile(skillMdPath, source, false);
|
|
5753
|
+
results.push(new Skill(parsed));
|
|
5754
|
+
} catch (error) {
|
|
5755
|
+
onWarning?.(
|
|
5756
|
+
`Failed to parse ${skillMdPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
5757
|
+
);
|
|
5758
|
+
}
|
|
5759
|
+
return;
|
|
5760
|
+
}
|
|
5761
|
+
for (const entry of entries) {
|
|
5762
|
+
if (entry.isDirectory() && !entry.name.startsWith(".")) {
|
|
5763
|
+
scanForSkills(path2.join(dir, entry.name), source, results, onWarning);
|
|
5764
|
+
}
|
|
5765
|
+
}
|
|
5766
|
+
}
|
|
5767
|
+
var SKILLS_DIR_NAME, CONFIG_DIR_NAME;
|
|
5768
|
+
var init_loader = __esm({
|
|
5769
|
+
"src/skills/loader.ts"() {
|
|
5770
|
+
"use strict";
|
|
5771
|
+
init_parser();
|
|
5772
|
+
init_registry2();
|
|
5773
|
+
init_skill();
|
|
5774
|
+
SKILLS_DIR_NAME = "skills";
|
|
5775
|
+
CONFIG_DIR_NAME = ".llmist";
|
|
5776
|
+
}
|
|
5777
|
+
});
|
|
5778
|
+
|
|
5779
|
+
// src/skills/use-skill-gadget.ts
|
|
5780
|
+
import { z as z4 } from "zod";
|
|
5781
|
+
function createUseSkillGadget(registry) {
|
|
5782
|
+
const summaries = registry.getMetadataSummaries();
|
|
5783
|
+
const skillNames = registry.getModelInvocable().map((s) => s.name);
|
|
5784
|
+
const description = [
|
|
5785
|
+
"Activate a skill to get specialized instructions for a task.",
|
|
5786
|
+
"Available skills:",
|
|
5787
|
+
summaries
|
|
5788
|
+
].join("\n");
|
|
5789
|
+
return createGadget({
|
|
5790
|
+
name: USE_SKILL_GADGET_NAME,
|
|
5791
|
+
description,
|
|
5792
|
+
schema: z4.object({
|
|
5793
|
+
skill: z4.enum(skillNames).describe("Name of the skill to activate"),
|
|
5794
|
+
arguments: z4.string().optional().describe("Arguments for the skill (e.g., a filename, issue number, or search query)")
|
|
5795
|
+
}),
|
|
5796
|
+
execute: async ({ skill: skillName, arguments: args }) => {
|
|
5797
|
+
const skill = registry.get(skillName);
|
|
5798
|
+
if (!skill) {
|
|
5799
|
+
return `Unknown skill: "${skillName}". Available skills: ${skillNames.join(", ")}`;
|
|
5800
|
+
}
|
|
5801
|
+
const activation = await skill.activate({
|
|
5802
|
+
arguments: args,
|
|
5803
|
+
cwd: process.cwd()
|
|
5804
|
+
});
|
|
5805
|
+
return activation.resolvedInstructions;
|
|
5806
|
+
}
|
|
5807
|
+
});
|
|
5808
|
+
}
|
|
5809
|
+
var USE_SKILL_GADGET_NAME;
|
|
5810
|
+
var init_use_skill_gadget = __esm({
|
|
5811
|
+
"src/skills/use-skill-gadget.ts"() {
|
|
5812
|
+
"use strict";
|
|
5813
|
+
init_create_gadget();
|
|
5814
|
+
USE_SKILL_GADGET_NAME = "UseSkill";
|
|
5815
|
+
}
|
|
5816
|
+
});
|
|
5817
|
+
|
|
5193
5818
|
// src/agent/builder-utils.ts
|
|
5194
5819
|
function formatGadgetCall(gadgetName, invocationId, parameters, prefixes) {
|
|
5195
5820
|
const startPrefix = prefixes?.start ?? GADGET_START_PREFIX;
|
|
@@ -12194,6 +12819,10 @@ var init_builder = __esm({
|
|
|
12194
12819
|
"use strict";
|
|
12195
12820
|
init_model_shortcuts();
|
|
12196
12821
|
init_registry();
|
|
12822
|
+
init_activation();
|
|
12823
|
+
init_loader();
|
|
12824
|
+
init_parser();
|
|
12825
|
+
init_use_skill_gadget();
|
|
12197
12826
|
init_agent();
|
|
12198
12827
|
init_agent_internal_key();
|
|
12199
12828
|
init_builder_utils();
|
|
@@ -12205,12 +12834,14 @@ var init_builder = __esm({
|
|
|
12205
12834
|
retry;
|
|
12206
12835
|
subagents;
|
|
12207
12836
|
policies;
|
|
12837
|
+
skills;
|
|
12208
12838
|
constructor(client) {
|
|
12209
12839
|
this.core = { client, initialMessages: [] };
|
|
12210
12840
|
this.gadgets = { gadgets: [] };
|
|
12211
12841
|
this.retry = {};
|
|
12212
12842
|
this.subagents = {};
|
|
12213
12843
|
this.policies = {};
|
|
12844
|
+
this.skills = { preActivated: [], skillDirs: [] };
|
|
12214
12845
|
}
|
|
12215
12846
|
/** Set the model to use. Supports aliases like "sonnet", "flash". */
|
|
12216
12847
|
withModel(model) {
|
|
@@ -12347,6 +12978,38 @@ var init_builder = __esm({
|
|
|
12347
12978
|
this.policies.compactionConfig = { enabled: false };
|
|
12348
12979
|
return this;
|
|
12349
12980
|
}
|
|
12981
|
+
// ─── Skills ──────────────────────────────────────────────────────────────────
|
|
12982
|
+
/** Register a skill registry for this agent. */
|
|
12983
|
+
withSkills(registry) {
|
|
12984
|
+
this.skills.registry = registry;
|
|
12985
|
+
return this;
|
|
12986
|
+
}
|
|
12987
|
+
/**
|
|
12988
|
+
* Pre-activate a specific skill before the agent starts.
|
|
12989
|
+
* Instructions are injected into the system prompt.
|
|
12990
|
+
*
|
|
12991
|
+
* Note: each call replaces (not appends) the pre-activated skill for that name.
|
|
12992
|
+
* This is safe for REPL loops where the same builder is reused.
|
|
12993
|
+
*/
|
|
12994
|
+
withSkill(name, args) {
|
|
12995
|
+
const existing = this.skills.preActivated.findIndex((s) => s.name === name);
|
|
12996
|
+
if (existing !== -1) {
|
|
12997
|
+
this.skills.preActivated[existing] = { name, args };
|
|
12998
|
+
} else {
|
|
12999
|
+
this.skills.preActivated.push({ name, args });
|
|
13000
|
+
}
|
|
13001
|
+
return this;
|
|
13002
|
+
}
|
|
13003
|
+
/** Clear all pre-activated skills. Call between REPL iterations. */
|
|
13004
|
+
clearPreActivatedSkills() {
|
|
13005
|
+
this.skills.preActivated = [];
|
|
13006
|
+
return this;
|
|
13007
|
+
}
|
|
13008
|
+
/** Add a directory to scan for skills. */
|
|
13009
|
+
withSkillsFrom(dir) {
|
|
13010
|
+
this.skills.skillDirs.push(dir);
|
|
13011
|
+
return this;
|
|
13012
|
+
}
|
|
12350
13013
|
/** Configure retry behavior for LLM API calls. */
|
|
12351
13014
|
withRetry(config) {
|
|
12352
13015
|
this.retry.retryConfig = { ...config, enabled: config.enabled ?? true };
|
|
@@ -12438,16 +13101,75 @@ var init_builder = __esm({
|
|
|
12438
13101
|
composeHooks() {
|
|
12439
13102
|
return HookComposer.compose(this.core.hooks, this.core.trailingMessage);
|
|
12440
13103
|
}
|
|
13104
|
+
resolveSkillRegistry() {
|
|
13105
|
+
if (this.skills.registry) {
|
|
13106
|
+
if (this.skills.skillDirs.length > 0) {
|
|
13107
|
+
for (const dir of this.skills.skillDirs) {
|
|
13108
|
+
const skills = loadSkillsFromDirectory(dir, { type: "directory", path: dir });
|
|
13109
|
+
this.skills.registry.registerMany(skills);
|
|
13110
|
+
}
|
|
13111
|
+
}
|
|
13112
|
+
return this.skills.registry;
|
|
13113
|
+
}
|
|
13114
|
+
if (this.skills.skillDirs.length > 0) {
|
|
13115
|
+
const { SkillRegistry: SR } = (init_registry2(), __toCommonJS(registry_exports));
|
|
13116
|
+
const reg = new SR();
|
|
13117
|
+
for (const dir of this.skills.skillDirs) {
|
|
13118
|
+
const skills = loadSkillsFromDirectory(dir, { type: "directory", path: dir });
|
|
13119
|
+
reg.registerMany(skills);
|
|
13120
|
+
}
|
|
13121
|
+
return reg;
|
|
13122
|
+
}
|
|
13123
|
+
return void 0;
|
|
13124
|
+
}
|
|
13125
|
+
/**
|
|
13126
|
+
* Resolve pre-activated skill instructions synchronously.
|
|
13127
|
+
* Reads SKILL.md from disk via readFileSync (skills are local files).
|
|
13128
|
+
*/
|
|
13129
|
+
resolvePreActivatedInstructions(skillRegistry) {
|
|
13130
|
+
if (this.skills.preActivated.length === 0) return void 0;
|
|
13131
|
+
const fs4 = __require("fs");
|
|
13132
|
+
const blocks = [];
|
|
13133
|
+
for (const { name, args } of this.skills.preActivated) {
|
|
13134
|
+
const skill = skillRegistry.get(name);
|
|
13135
|
+
if (!skill) continue;
|
|
13136
|
+
const content = fs4.readFileSync(skill.sourcePath, "utf-8");
|
|
13137
|
+
const { body } = parseFrontmatter(content);
|
|
13138
|
+
const resolved = resolveInstructions(body, {
|
|
13139
|
+
arguments: args,
|
|
13140
|
+
variables: { SKILL_DIR: skill.sourceDir, CLAUDE_SKILL_DIR: skill.sourceDir },
|
|
13141
|
+
cwd: skill.sourceDir,
|
|
13142
|
+
shell: skill.metadata.shell
|
|
13143
|
+
});
|
|
13144
|
+
blocks.push(`## Skill: ${name}
|
|
13145
|
+
|
|
13146
|
+
${resolved}`);
|
|
13147
|
+
}
|
|
13148
|
+
return blocks.length > 0 ? blocks.join("\n\n---\n\n") : void 0;
|
|
13149
|
+
}
|
|
12441
13150
|
buildAgentOptions(userPrompt) {
|
|
12442
13151
|
if (!this.core.client) {
|
|
12443
13152
|
const { LLMist: LLMistClass } = (init_client(), __toCommonJS(client_exports));
|
|
12444
13153
|
this.core.client = new LLMistClass();
|
|
12445
13154
|
}
|
|
12446
13155
|
const registry = GadgetRegistry.from(this.gadgets.gadgets);
|
|
13156
|
+
let systemPrompt = this.core.systemPrompt;
|
|
13157
|
+
const skillRegistry = this.resolveSkillRegistry();
|
|
13158
|
+
if (skillRegistry && skillRegistry.size > 0) {
|
|
13159
|
+
if (skillRegistry.getModelInvocable().length > 0) {
|
|
13160
|
+
registry.registerByClass(createUseSkillGadget(skillRegistry));
|
|
13161
|
+
}
|
|
13162
|
+
const preActivatedBlock = this.resolvePreActivatedInstructions(skillRegistry);
|
|
13163
|
+
if (preActivatedBlock) {
|
|
13164
|
+
systemPrompt = systemPrompt ? `${systemPrompt}
|
|
13165
|
+
|
|
13166
|
+
${preActivatedBlock}` : preActivatedBlock;
|
|
13167
|
+
}
|
|
13168
|
+
}
|
|
12447
13169
|
return {
|
|
12448
13170
|
client: this.core.client,
|
|
12449
13171
|
model: this.core.model ?? "openai:gpt-5-nano",
|
|
12450
|
-
systemPrompt
|
|
13172
|
+
systemPrompt,
|
|
12451
13173
|
userPrompt,
|
|
12452
13174
|
registry,
|
|
12453
13175
|
maxIterations: this.core.maxIterations,
|
|
@@ -13132,8 +13854,8 @@ var init_error_formatter = __esm({
|
|
|
13132
13854
|
const parts = [];
|
|
13133
13855
|
parts.push(`Error: Invalid parameters for '${gadgetName}':`);
|
|
13134
13856
|
for (const issue of zodError.issues) {
|
|
13135
|
-
const
|
|
13136
|
-
parts.push(` - ${
|
|
13857
|
+
const path3 = issue.path.join(".") || "root";
|
|
13858
|
+
parts.push(` - ${path3}: ${issue.message}`);
|
|
13137
13859
|
}
|
|
13138
13860
|
parts.push("");
|
|
13139
13861
|
parts.push("Gadget Usage:");
|
|
@@ -13198,7 +13920,7 @@ function stripMarkdownFences(content) {
|
|
|
13198
13920
|
return cleaned.trim();
|
|
13199
13921
|
}
|
|
13200
13922
|
var globalInvocationCounter, GadgetCallParser;
|
|
13201
|
-
var
|
|
13923
|
+
var init_parser2 = __esm({
|
|
13202
13924
|
"src/gadgets/parser.ts"() {
|
|
13203
13925
|
"use strict";
|
|
13204
13926
|
init_constants();
|
|
@@ -13404,7 +14126,7 @@ var init_typed_gadget = __esm({
|
|
|
13404
14126
|
|
|
13405
14127
|
// src/gadgets/executor.ts
|
|
13406
14128
|
import equal from "fast-deep-equal";
|
|
13407
|
-
import { z as
|
|
14129
|
+
import { z as z5 } from "zod";
|
|
13408
14130
|
function getHostExportsInternal() {
|
|
13409
14131
|
return {
|
|
13410
14132
|
AgentBuilder,
|
|
@@ -13412,7 +14134,7 @@ function getHostExportsInternal() {
|
|
|
13412
14134
|
createGadget,
|
|
13413
14135
|
ExecutionTree,
|
|
13414
14136
|
LLMist,
|
|
13415
|
-
z:
|
|
14137
|
+
z: z5
|
|
13416
14138
|
};
|
|
13417
14139
|
}
|
|
13418
14140
|
var GadgetExecutor;
|
|
@@ -13430,7 +14152,7 @@ var init_executor = __esm({
|
|
|
13430
14152
|
init_create_gadget();
|
|
13431
14153
|
init_error_formatter();
|
|
13432
14154
|
init_exceptions();
|
|
13433
|
-
|
|
14155
|
+
init_parser2();
|
|
13434
14156
|
init_typed_gadget();
|
|
13435
14157
|
GadgetExecutor = class {
|
|
13436
14158
|
registry;
|
|
@@ -15031,7 +15753,7 @@ var init_stream_processor = __esm({
|
|
|
15031
15753
|
"src/agent/stream-processor.ts"() {
|
|
15032
15754
|
"use strict";
|
|
15033
15755
|
init_executor();
|
|
15034
|
-
|
|
15756
|
+
init_parser2();
|
|
15035
15757
|
init_logger();
|
|
15036
15758
|
init_gadget_concurrency_manager();
|
|
15037
15759
|
init_gadget_dependency_resolver();
|
|
@@ -16155,7 +16877,7 @@ init_builder();
|
|
|
16155
16877
|
init_event_handlers();
|
|
16156
16878
|
init_file_logging();
|
|
16157
16879
|
init_hook_presets();
|
|
16158
|
-
import { z as
|
|
16880
|
+
import { z as z6 } from "zod";
|
|
16159
16881
|
|
|
16160
16882
|
// src/agent/compaction/index.ts
|
|
16161
16883
|
init_config();
|
|
@@ -16464,7 +17186,7 @@ function resultWithFile(result, fileData, mimeType, options) {
|
|
|
16464
17186
|
|
|
16465
17187
|
// src/index.ts
|
|
16466
17188
|
init_output_viewer();
|
|
16467
|
-
|
|
17189
|
+
init_parser2();
|
|
16468
17190
|
init_registry();
|
|
16469
17191
|
init_typed_gadget();
|
|
16470
17192
|
init_constants2();
|
|
@@ -16731,6 +17453,14 @@ var SimpleSessionManager = class extends BaseSessionManager {
|
|
|
16731
17453
|
}
|
|
16732
17454
|
};
|
|
16733
17455
|
|
|
17456
|
+
// src/skills/index.ts
|
|
17457
|
+
init_activation();
|
|
17458
|
+
init_loader();
|
|
17459
|
+
init_parser();
|
|
17460
|
+
init_registry2();
|
|
17461
|
+
init_skill();
|
|
17462
|
+
init_use_skill_gadget();
|
|
17463
|
+
|
|
16734
17464
|
// src/utils/format.ts
|
|
16735
17465
|
function truncate(text3, maxLength, suffix = "...") {
|
|
16736
17466
|
if (text3.length <= maxLength) return text3;
|
|
@@ -16926,11 +17656,14 @@ export {
|
|
|
16926
17656
|
OpenRouterProvider,
|
|
16927
17657
|
RateLimitTracker,
|
|
16928
17658
|
SimpleSessionManager,
|
|
17659
|
+
Skill,
|
|
17660
|
+
SkillRegistry,
|
|
16929
17661
|
SlidingWindowStrategy,
|
|
16930
17662
|
StreamProcessor,
|
|
16931
17663
|
SummarizationStrategy,
|
|
16932
17664
|
TaskCompletionSignal,
|
|
16933
17665
|
TimeoutException,
|
|
17666
|
+
USE_SKILL_GADGET_NAME,
|
|
16934
17667
|
audioFromBase64,
|
|
16935
17668
|
audioFromBuffer,
|
|
16936
17669
|
collectEvents,
|
|
@@ -16948,10 +17681,12 @@ export {
|
|
|
16948
17681
|
createOpenAIProviderFromEnv,
|
|
16949
17682
|
createOpenRouterProviderFromEnv,
|
|
16950
17683
|
createSubagent,
|
|
17684
|
+
createUseSkillGadget,
|
|
16951
17685
|
defaultLogger,
|
|
16952
17686
|
detectAudioMimeType,
|
|
16953
17687
|
detectImageMimeType,
|
|
16954
17688
|
discoverProviderAdapters,
|
|
17689
|
+
discoverSkills,
|
|
16955
17690
|
extractMessageText,
|
|
16956
17691
|
extractRetryAfterMs,
|
|
16957
17692
|
filterByDepth,
|
|
@@ -16994,15 +17729,21 @@ export {
|
|
|
16994
17729
|
iterationProgressHint,
|
|
16995
17730
|
listPresets,
|
|
16996
17731
|
listSubagents,
|
|
17732
|
+
loadSkillsFromDirectory,
|
|
16997
17733
|
normalizeMessageContent,
|
|
16998
17734
|
parallelGadgetHint,
|
|
16999
17735
|
parseDataUrl,
|
|
17736
|
+
parseFrontmatter,
|
|
17000
17737
|
parseManifest,
|
|
17738
|
+
parseMetadata,
|
|
17001
17739
|
parseRetryAfterHeader,
|
|
17740
|
+
parseSkillContent,
|
|
17741
|
+
parseSkillFile,
|
|
17002
17742
|
randomDelay,
|
|
17003
17743
|
resetFileLoggingState,
|
|
17004
17744
|
resolveConfig,
|
|
17005
17745
|
resolveHintTemplate,
|
|
17746
|
+
resolveInstructions,
|
|
17006
17747
|
resolveModel,
|
|
17007
17748
|
resolvePromptTemplate,
|
|
17008
17749
|
resolveRateLimitConfig,
|
|
@@ -17017,9 +17758,12 @@ export {
|
|
|
17017
17758
|
resultWithImages,
|
|
17018
17759
|
resultWithMedia,
|
|
17019
17760
|
runWithHandlers,
|
|
17761
|
+
scanResources,
|
|
17020
17762
|
schemaToJSONSchema,
|
|
17021
17763
|
stream,
|
|
17022
17764
|
stripProviderPrefix,
|
|
17765
|
+
substituteArguments,
|
|
17766
|
+
substituteVariables,
|
|
17023
17767
|
text,
|
|
17024
17768
|
timing,
|
|
17025
17769
|
toBase64,
|
|
@@ -17027,9 +17771,10 @@ export {
|
|
|
17027
17771
|
validateAndApplyDefaults,
|
|
17028
17772
|
validateGadgetParams,
|
|
17029
17773
|
validateGadgetSchema,
|
|
17774
|
+
validateMetadata,
|
|
17030
17775
|
withErrorHandling,
|
|
17031
17776
|
withRetry,
|
|
17032
17777
|
withTimeout,
|
|
17033
|
-
|
|
17778
|
+
z6 as z
|
|
17034
17779
|
};
|
|
17035
17780
|
//# sourceMappingURL=index.js.map
|