@theokit/sdk 2.24.0 → 2.25.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 CHANGED
@@ -575,10 +575,10 @@ function buildToolPrompt(prompt) {
575
575
  Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
576
576
  }
577
577
  function setupStructuredOutput(schema, maxRetries) {
578
- const z8 = requireZod();
578
+ const z9 = requireZod();
579
579
  const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
580
580
  return {
581
- z: z8,
581
+ z: z9,
582
582
  jsonSchema,
583
583
  maxRetries: maxRetries ?? 1,
584
584
  initialUsage: { inputTokens: 0, outputTokens: 0 }
@@ -6046,7 +6046,8 @@ function stripSecretsFromOptions(options) {
6046
6046
  local: serializeLocal(options.local),
6047
6047
  cloud: serializeCloud(options.cloud),
6048
6048
  memory: serializeMemory(options.memory),
6049
- skills: serializeEnabledList(options.skills),
6049
+ // SE22 — a SkillsResolver function isn't serializable; persist only the static form.
6050
+ skills: serializeEnabledList(typeof options.skills === "function" ? void 0 : options.skills),
6050
6051
  // Code-`Plugin` objects are closures and cannot be persisted (like custom
6051
6052
  // tools); only the named-enable settings form is serialized.
6052
6053
  plugins: serializeEnabledList(asPluginsSettings(options.plugins)),
@@ -6354,6 +6355,7 @@ function serializeCloud2(cloud) {
6354
6355
  return result;
6355
6356
  }
6356
6357
  function serializeSkills(skills) {
6358
+ if (typeof skills === "function") return void 0;
6357
6359
  if (skills?.enabled === void 0 || skills.enabled.length === 0) return void 0;
6358
6360
  return { enabled: [...skills.enabled] };
6359
6361
  }
@@ -7734,6 +7736,7 @@ init_errors();
7734
7736
  function validateCloudToolParity(options) {
7735
7737
  if (options.cloud === void 0) return;
7736
7738
  rejectFunctionSystemPrompt(options);
7739
+ rejectFunctionSkills(options);
7737
7740
  rejectStdioMcpLocalPaths(options);
7738
7741
  }
7739
7742
  function rejectFunctionSystemPrompt(options) {
@@ -7744,6 +7747,14 @@ function rejectFunctionSystemPrompt(options) {
7744
7747
  );
7745
7748
  }
7746
7749
  }
7750
+ function rejectFunctionSkills(options) {
7751
+ if (typeof options.skills === "function") {
7752
+ throw new exports.ConfigurationError(
7753
+ "Cloud agents require skills as a static settings object. SkillsResolver functions can't run on PaaS \u2014 resolve to a SkillsSettings object before Agent.create() or move the dynamic logic into a hook rule.",
7754
+ { code: "cloud_incompatible_function_resolver" }
7755
+ );
7756
+ }
7757
+ }
7747
7758
  function rejectStdioMcpLocalPaths(options) {
7748
7759
  if (options.mcpServers === void 0) return;
7749
7760
  for (const [name, config] of Object.entries(options.mcpServers)) {
@@ -9570,9 +9581,224 @@ function parseFrontmatterFields(frontmatter) {
9570
9581
  return out;
9571
9582
  }
9572
9583
 
9584
+ // src/internal/runtime/skills/discover-skills.ts
9585
+ init_errors();
9586
+ init_path_guard();
9587
+
9588
+ // src/internal/runtime/skills/skill-frontmatter.ts
9589
+ init_errors();
9590
+ init_yaml_frontmatter();
9591
+ function asString(v) {
9592
+ return typeof v === "string" ? v : void 0;
9593
+ }
9594
+ function toStringFields(raw) {
9595
+ const out = {};
9596
+ for (const [k, v] of Object.entries(raw)) out[k] = asString(v);
9597
+ return out;
9598
+ }
9599
+ function parseSkillFrontmatter(raw, fallbackName) {
9600
+ const fields = extractAndParseFrontmatter(raw, fallbackName);
9601
+ const name = resolveName(fields, fallbackName);
9602
+ ensureRequiredFields(fields, name);
9603
+ return buildFrontmatter(fields, name);
9604
+ }
9605
+ function stripSkillFrontmatter(raw) {
9606
+ const match = /^---\s*\n[\s\S]*?\n---\s*\n/.exec(raw);
9607
+ return (match === null ? raw : raw.slice(match[0].length)).trim();
9608
+ }
9609
+ function extractAndParseFrontmatter(raw, fallbackName) {
9610
+ const match = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(raw);
9611
+ if (match === null) {
9612
+ throw new exports.ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {
9613
+ code: "missing_frontmatter"
9614
+ });
9615
+ }
9616
+ const frontmatter = match[1] ?? "";
9617
+ try {
9618
+ return toStringFields(parseSimpleYaml(frontmatter));
9619
+ } catch (cause) {
9620
+ const detail = cause instanceof Error ? cause.message : String(cause);
9621
+ throw new exports.ConfigurationError(
9622
+ `Skill ${fallbackName} has malformed YAML frontmatter: ${detail}`,
9623
+ { code: "schema_invalid", cause }
9624
+ );
9625
+ }
9626
+ }
9627
+ function resolveName(fields, fallbackName) {
9628
+ if (hasContent(fields.name)) return fields.name;
9629
+ if (hasContent(fallbackName)) return fallbackName;
9630
+ throw new exports.ConfigurationError("Skill at unknown path is missing required field: name", {
9631
+ code: "schema_invalid"
9632
+ });
9633
+ }
9634
+ function ensureRequiredFields(fields, name) {
9635
+ if (!hasContent(fields.description)) {
9636
+ throw new exports.ConfigurationError(`Skill ${name} is missing required field: description`, {
9637
+ code: "schema_invalid"
9638
+ });
9639
+ }
9640
+ }
9641
+ function buildFrontmatter(fields, name) {
9642
+ const description = fields.description;
9643
+ if (description === void 0) {
9644
+ throw new exports.ConfigurationError(`Skill ${name} missing description`, { code: "schema_invalid" });
9645
+ }
9646
+ const result = { name, description };
9647
+ if (hasContent(fields.category)) result.category = fields.category;
9648
+ const deps = parseDependencies(fields.dependencies);
9649
+ if (deps !== void 0) result.dependencies = deps;
9650
+ return result;
9651
+ }
9652
+ function parseDependencies(raw) {
9653
+ if (!hasContent(raw)) return void 0;
9654
+ const deps = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
9655
+ return deps.length > 0 ? deps : void 0;
9656
+ }
9657
+ function hasContent(value) {
9658
+ return value !== void 0 && value.trim().length > 0;
9659
+ }
9660
+
9661
+ // src/internal/runtime/skills/discover-skills.ts
9662
+ async function discoverSkills(dir, options) {
9663
+ let entries;
9664
+ try {
9665
+ entries = await readWorkspaceDir(dir, "skills_read_error", "skills directory");
9666
+ } catch {
9667
+ return [];
9668
+ }
9669
+ const skills = [];
9670
+ for (const entry of entries) {
9671
+ if (!entry.isDirectory()) continue;
9672
+ let skillDir;
9673
+ try {
9674
+ skillDir = safePathJoin(dir, entry.name);
9675
+ assertNoSymlinkEscape(skillDir, dir);
9676
+ } catch {
9677
+ continue;
9678
+ }
9679
+ const skillPath = path.join(skillDir, "SKILL.md");
9680
+ let raw;
9681
+ try {
9682
+ raw = await promises.readFile(skillPath, "utf8");
9683
+ } catch {
9684
+ continue;
9685
+ }
9686
+ const skill = tryParseSkill(raw, entry.name, skillPath, options);
9687
+ if (skill !== void 0) skills.push(skill);
9688
+ }
9689
+ return skills;
9690
+ }
9691
+ function tryParseSkill(raw, fallbackName, source, options) {
9692
+ try {
9693
+ const frontmatter = parseSkillFrontmatter(raw, fallbackName);
9694
+ const skill = {
9695
+ name: frontmatter.name,
9696
+ description: frontmatter.description,
9697
+ source
9698
+ };
9699
+ if (frontmatter.category !== void 0) skill.category = frontmatter.category;
9700
+ if (frontmatter.dependencies !== void 0) skill.dependencies = frontmatter.dependencies;
9701
+ return skill;
9702
+ } catch (cause) {
9703
+ if (cause instanceof exports.ConfigurationError) {
9704
+ options?.onInvalidSkill?.({
9705
+ name: fallbackName,
9706
+ source,
9707
+ code: cause.code ?? "unknown",
9708
+ message: cause.message
9709
+ });
9710
+ return void 0;
9711
+ }
9712
+ throw cause;
9713
+ }
9714
+ }
9715
+
9716
+ // src/internal/runtime/skills/skills-manager.ts
9717
+ var SkillsManager = class {
9718
+ constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
9719
+ this.cwd = cwd;
9720
+ this.settingSourcesIncludeProject = settingSourcesIncludeProject;
9721
+ this.skillsDir = skillsDir;
9722
+ this.inline = inline;
9723
+ }
9724
+ cwd;
9725
+ settingSourcesIncludeProject;
9726
+ skillsDir;
9727
+ inline;
9728
+ skills = [];
9729
+ async initialize() {
9730
+ if (!this.settingSourcesIncludeProject) {
9731
+ this.skills = this.mergeInline([]);
9732
+ return;
9733
+ }
9734
+ await this.refresh();
9735
+ }
9736
+ async refresh() {
9737
+ const skillsRoot = this.skillsDir ?? path.join(this.cwd, ".theokit", "skills");
9738
+ const discovered = await discoverSkills(skillsRoot, {
9739
+ onInvalidSkill: (info) => {
9740
+ process.stderr.write(
9741
+ `[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
9742
+ `
9743
+ );
9744
+ }
9745
+ });
9746
+ this.skills = this.mergeInline(discovered);
9747
+ }
9748
+ /** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
9749
+ mergeInline(discovered) {
9750
+ if (this.inline === void 0 || this.inline.length === 0) return discovered;
9751
+ const inlineNames = new Set(this.inline.map((s) => s.name));
9752
+ return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
9753
+ }
9754
+ list() {
9755
+ return Promise.resolve(this.skills);
9756
+ }
9757
+ /**
9758
+ * SE20 — resolve a skill by name INCLUDING its body. Inline (`createSkill`)
9759
+ * skills carry `instructions` on the object; filesystem skills read the body
9760
+ * from their `source` SKILL.md (frontmatter stripped). `undefined` when no
9761
+ * enabled skill matches (malformed skills were already excluded at discovery).
9762
+ */
9763
+ async get(name) {
9764
+ const skill = this.skills.find((s) => s.name === name);
9765
+ if (skill === void 0) return void 0;
9766
+ const instructions = typeof skill.instructions === "string" ? skill.instructions : stripSkillFrontmatter(await promises.readFile(skill.source, "utf8"));
9767
+ const references = skill.references;
9768
+ return {
9769
+ name: skill.name,
9770
+ description: skill.description,
9771
+ instructions,
9772
+ ...references !== void 0 ? { references } : {}
9773
+ };
9774
+ }
9775
+ };
9776
+
9573
9777
  // src/internal/runtime/system-prompt/local-assembly.ts
9574
- async function buildSystemPromptContext(inputs, userText, memoryFacts) {
9575
- const skills = inputs.skillsManager !== void 0 ? await inputs.skillsManager.list() : [];
9778
+ async function resolveSendSkills(inputs, userText, memoryFacts) {
9779
+ const skills = inputs.options.skills;
9780
+ if (typeof skills !== "function") {
9781
+ return { manager: inputs.skillsManager, autoInject: skills?.autoInject ?? true };
9782
+ }
9783
+ const settings = await skills({
9784
+ agentId: inputs.agentId,
9785
+ cwd: inputs.workspaceCwd,
9786
+ model: inputs.model,
9787
+ userMessage: userText,
9788
+ memory: memoryFacts.map((fact) => ({ text: fact.text }))
9789
+ });
9790
+ const manager = new SkillsManager(
9791
+ inputs.workspaceCwd,
9792
+ settings.enabled,
9793
+ inputs.settingSourcesIncludeProject,
9794
+ settings.skillsDir,
9795
+ settings.inline
9796
+ );
9797
+ await manager.initialize();
9798
+ return { manager, autoInject: settings.autoInject ?? true };
9799
+ }
9800
+ async function buildSystemPromptContext(inputs, userText, memoryFacts, manager = inputs.skillsManager) {
9801
+ const skills = manager !== void 0 ? await manager.list() : [];
9576
9802
  return {
9577
9803
  agentId: inputs.agentId,
9578
9804
  cwd: inputs.workspaceCwd,
@@ -9583,10 +9809,11 @@ async function buildSystemPromptContext(inputs, userText, memoryFacts) {
9583
9809
  };
9584
9810
  }
9585
9811
  async function buildAssemblyContext(inputs, userText, baseSystemPrompt, memoryFacts, activeMemorySummary) {
9586
- const baseCtx = await buildSystemPromptContext(inputs, userText, memoryFacts);
9812
+ const resolved = await resolveSendSkills(inputs, userText, memoryFacts);
9813
+ const baseCtx = await buildSystemPromptContext(inputs, userText, memoryFacts, resolved.manager);
9587
9814
  const assemblyCtx = {
9588
9815
  ...baseCtx,
9589
- skillsAutoInject: inputs.options.skills?.autoInject ?? true,
9816
+ skillsAutoInject: resolved.autoInject,
9590
9817
  memoryAutoInject: inputs.options.memory?.autoInject ?? true
9591
9818
  };
9592
9819
  if (baseSystemPrompt !== void 0) assemblyCtx.baseSystemPrompt = baseSystemPrompt;
@@ -10839,177 +11066,6 @@ async function loadPluginManifestFromMarkdown(pluginsRoot, folderName) {
10839
11066
  return metadata;
10840
11067
  }
10841
11068
 
10842
- // src/internal/runtime/skills/discover-skills.ts
10843
- init_errors();
10844
- init_path_guard();
10845
-
10846
- // src/internal/runtime/skills/skill-frontmatter.ts
10847
- init_errors();
10848
- init_yaml_frontmatter();
10849
- function asString(v) {
10850
- return typeof v === "string" ? v : void 0;
10851
- }
10852
- function toStringFields(raw) {
10853
- const out = {};
10854
- for (const [k, v] of Object.entries(raw)) out[k] = asString(v);
10855
- return out;
10856
- }
10857
- function parseSkillFrontmatter(raw, fallbackName) {
10858
- const fields = extractAndParseFrontmatter(raw, fallbackName);
10859
- const name = resolveName(fields, fallbackName);
10860
- ensureRequiredFields(fields, name);
10861
- return buildFrontmatter(fields, name);
10862
- }
10863
- function extractAndParseFrontmatter(raw, fallbackName) {
10864
- const match = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(raw);
10865
- if (match === null) {
10866
- throw new exports.ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {
10867
- code: "missing_frontmatter"
10868
- });
10869
- }
10870
- const frontmatter = match[1] ?? "";
10871
- try {
10872
- return toStringFields(parseSimpleYaml(frontmatter));
10873
- } catch (cause) {
10874
- const detail = cause instanceof Error ? cause.message : String(cause);
10875
- throw new exports.ConfigurationError(
10876
- `Skill ${fallbackName} has malformed YAML frontmatter: ${detail}`,
10877
- { code: "schema_invalid", cause }
10878
- );
10879
- }
10880
- }
10881
- function resolveName(fields, fallbackName) {
10882
- if (hasContent(fields.name)) return fields.name;
10883
- if (hasContent(fallbackName)) return fallbackName;
10884
- throw new exports.ConfigurationError("Skill at unknown path is missing required field: name", {
10885
- code: "schema_invalid"
10886
- });
10887
- }
10888
- function ensureRequiredFields(fields, name) {
10889
- if (!hasContent(fields.description)) {
10890
- throw new exports.ConfigurationError(`Skill ${name} is missing required field: description`, {
10891
- code: "schema_invalid"
10892
- });
10893
- }
10894
- }
10895
- function buildFrontmatter(fields, name) {
10896
- const description = fields.description;
10897
- if (description === void 0) {
10898
- throw new exports.ConfigurationError(`Skill ${name} missing description`, { code: "schema_invalid" });
10899
- }
10900
- const result = { name, description };
10901
- if (hasContent(fields.category)) result.category = fields.category;
10902
- const deps = parseDependencies(fields.dependencies);
10903
- if (deps !== void 0) result.dependencies = deps;
10904
- return result;
10905
- }
10906
- function parseDependencies(raw) {
10907
- if (!hasContent(raw)) return void 0;
10908
- const deps = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
10909
- return deps.length > 0 ? deps : void 0;
10910
- }
10911
- function hasContent(value) {
10912
- return value !== void 0 && value.trim().length > 0;
10913
- }
10914
-
10915
- // src/internal/runtime/skills/discover-skills.ts
10916
- async function discoverSkills(dir, options) {
10917
- let entries;
10918
- try {
10919
- entries = await readWorkspaceDir(dir, "skills_read_error", "skills directory");
10920
- } catch {
10921
- return [];
10922
- }
10923
- const skills = [];
10924
- for (const entry of entries) {
10925
- if (!entry.isDirectory()) continue;
10926
- let skillDir;
10927
- try {
10928
- skillDir = safePathJoin(dir, entry.name);
10929
- assertNoSymlinkEscape(skillDir, dir);
10930
- } catch {
10931
- continue;
10932
- }
10933
- const skillPath = path.join(skillDir, "SKILL.md");
10934
- let raw;
10935
- try {
10936
- raw = await promises.readFile(skillPath, "utf8");
10937
- } catch {
10938
- continue;
10939
- }
10940
- const skill = tryParseSkill(raw, entry.name, skillPath, options);
10941
- if (skill !== void 0) skills.push(skill);
10942
- }
10943
- return skills;
10944
- }
10945
- function tryParseSkill(raw, fallbackName, source, options) {
10946
- try {
10947
- const frontmatter = parseSkillFrontmatter(raw, fallbackName);
10948
- const skill = {
10949
- name: frontmatter.name,
10950
- description: frontmatter.description,
10951
- source
10952
- };
10953
- if (frontmatter.category !== void 0) skill.category = frontmatter.category;
10954
- if (frontmatter.dependencies !== void 0) skill.dependencies = frontmatter.dependencies;
10955
- return skill;
10956
- } catch (cause) {
10957
- if (cause instanceof exports.ConfigurationError) {
10958
- options?.onInvalidSkill?.({
10959
- name: fallbackName,
10960
- source,
10961
- code: cause.code ?? "unknown",
10962
- message: cause.message
10963
- });
10964
- return void 0;
10965
- }
10966
- throw cause;
10967
- }
10968
- }
10969
-
10970
- // src/internal/runtime/skills/skills-manager.ts
10971
- var SkillsManager = class {
10972
- constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
10973
- this.cwd = cwd;
10974
- this.settingSourcesIncludeProject = settingSourcesIncludeProject;
10975
- this.skillsDir = skillsDir;
10976
- this.inline = inline;
10977
- }
10978
- cwd;
10979
- settingSourcesIncludeProject;
10980
- skillsDir;
10981
- inline;
10982
- skills = [];
10983
- async initialize() {
10984
- if (!this.settingSourcesIncludeProject) {
10985
- this.skills = this.mergeInline([]);
10986
- return;
10987
- }
10988
- await this.refresh();
10989
- }
10990
- async refresh() {
10991
- const skillsRoot = this.skillsDir ?? path.join(this.cwd, ".theokit", "skills");
10992
- const discovered = await discoverSkills(skillsRoot, {
10993
- onInvalidSkill: (info) => {
10994
- process.stderr.write(
10995
- `[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
10996
- `
10997
- );
10998
- }
10999
- });
11000
- this.skills = this.mergeInline(discovered);
11001
- }
11002
- /** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
11003
- mergeInline(discovered) {
11004
- if (this.inline === void 0 || this.inline.length === 0) return discovered;
11005
- const inlineNames = new Set(this.inline.map((s) => s.name));
11006
- return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
11007
- }
11008
- list() {
11009
- return Promise.resolve(this.skills);
11010
- }
11011
- };
11012
-
11013
11069
  // src/internal/runtime/local-agent/local-agent-bootstrap.ts
11014
11070
  function registerLocalAgent(args) {
11015
11071
  registerAgent({
@@ -11045,16 +11101,23 @@ function bootstrapSubmanagers(args) {
11045
11101
  );
11046
11102
  }
11047
11103
  if (args.options.skills !== void 0 || args.settingSourcesIncludeProject) {
11104
+ const staticSkills = typeof args.options.skills === "function" ? void 0 : args.options.skills;
11048
11105
  out.skillsManager = new SkillsManager(
11049
11106
  args.workspaceCwd,
11050
- args.options.skills?.enabled,
11107
+ staticSkills?.enabled,
11051
11108
  args.settingSourcesIncludeProject,
11052
11109
  // M22 — custom skills directory + inline (code-defined) skills.
11053
- args.options.skills?.skillsDir,
11054
- args.options.skills?.inline
11110
+ staticSkills?.skillsDir,
11111
+ staticSkills?.inline
11055
11112
  );
11056
11113
  const localSkills = out.skillsManager;
11057
- out.skills = { list: () => localSkills.list() };
11114
+ out.skills = {
11115
+ // Project to the public shape (name + description only). Inline skills carry
11116
+ // their body + references on the object; `list()` must never leak them —
11117
+ // the body is reachable exclusively through `get()`.
11118
+ list: async () => (await localSkills.list()).map((s) => ({ name: s.name, description: s.description })),
11119
+ get: (name) => localSkills.get(name)
11120
+ };
11058
11121
  }
11059
11122
  if (args.options.plugins !== void 0 || args.settingSourcesIncludePlugins) {
11060
11123
  out.pluginsManager = new PluginsManager(
@@ -17968,7 +18031,7 @@ var LocalAgent = class {
17968
18031
  }
17969
18032
  // biome-ignore format: G8 budget — thin accessor for the assembly inputs.
17970
18033
  assemblyInputs() {
17971
- return { agentId: this.agentId, workspaceCwd: this.workspaceCwd, model: this.model, options: this.options, context: this.context, skillsManager: this.skillsManager, systemPromptPipeline: this.systemPromptPipeline };
18034
+ return { agentId: this.agentId, workspaceCwd: this.workspaceCwd, model: this.model, options: this.options, context: this.context, skillsManager: this.skillsManager, settingSourcesIncludeProject: this.settingSourcesIncludeProject, systemPromptPipeline: this.systemPromptPipeline };
17972
18035
  }
17973
18036
  async resolveSystemPrompt(userText, options, memoryFacts) {
17974
18037
  const base = await resolveSystemPromptForSend(
@@ -19088,7 +19151,8 @@ function createSkill(spec) {
19088
19151
  source: `inline://${spec.name}`,
19089
19152
  instructions: spec.instructions,
19090
19153
  ...spec.category !== void 0 ? { category: spec.category } : {},
19091
- ...spec.dependencies !== void 0 ? { dependencies: spec.dependencies } : {}
19154
+ ...spec.dependencies !== void 0 ? { dependencies: spec.dependencies } : {},
19155
+ ...spec.references !== void 0 ? { references: spec.references } : {}
19092
19156
  };
19093
19157
  }
19094
19158
 
@@ -19515,6 +19579,46 @@ function defineProvider(profile, opts) {
19515
19579
  };
19516
19580
  }
19517
19581
 
19582
+ // src/define-skill-read-tool.ts
19583
+ init_to_json_schema();
19584
+ var SkillReadInputSchema = zod.z.object({
19585
+ name: zod.z.string().min(1, "skill_read: `name` is required.")
19586
+ });
19587
+ function renderSkill(skill) {
19588
+ const parts = [`# Skill: ${skill.name}`, "", skill.instructions];
19589
+ const refs = skill.references;
19590
+ if (refs !== void 0 && Object.keys(refs).length > 0) {
19591
+ parts.push("", "## References");
19592
+ for (const [file, content] of Object.entries(refs)) {
19593
+ parts.push("", `### ${file}`, content);
19594
+ }
19595
+ }
19596
+ return parts.join("\n");
19597
+ }
19598
+ function defineSkillReadTool(skills) {
19599
+ const seen = /* @__PURE__ */ new Set();
19600
+ for (const skill of skills) {
19601
+ if (seen.has(skill.name)) {
19602
+ throw new Error(`defineSkillReadTool: duplicate skill name "${skill.name}".`);
19603
+ }
19604
+ seen.add(skill.name);
19605
+ }
19606
+ return {
19607
+ name: "skill_read",
19608
+ description: "Read a skill's full instructions (and any bundled reference documents) by its name. Use this to load the body of a skill listed in the <skills> block before acting on it.",
19609
+ inputSchema: toJsonSchema(SkillReadInputSchema),
19610
+ handler: (input) => {
19611
+ const { name } = SkillReadInputSchema.parse(input);
19612
+ const skill = skills.find((s) => s.name === name);
19613
+ if (skill === void 0) {
19614
+ const available = skills.map((s) => s.name).join(", ");
19615
+ return `Skill "${name}" not found. Available skills: ${available.length > 0 ? available : "(none)"}.`;
19616
+ }
19617
+ return renderSkill(skill);
19618
+ }
19619
+ };
19620
+ }
19621
+
19518
19622
  // src/define-tool.ts
19519
19623
  init_to_json_schema();
19520
19624
  function shapeToolResult(spec, out) {
@@ -21440,6 +21544,7 @@ exports.createSkill = createSkill;
21440
21544
  exports.createSquad = createSquad;
21441
21545
  exports.definePlugin = definePlugin;
21442
21546
  exports.defineProvider = defineProvider;
21547
+ exports.defineSkillReadTool = defineSkillReadTool;
21443
21548
  exports.defineTool = defineTool;
21444
21549
  exports.emitRunEvent = emitRunEvent;
21445
21550
  exports.extractRawId = extractRawId;