@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/a2a/index.js CHANGED
@@ -1550,7 +1550,8 @@ function stripSecretsFromOptions(options) {
1550
1550
  local: serializeLocal(options.local),
1551
1551
  cloud: serializeCloud(options.cloud),
1552
1552
  memory: serializeMemory(options.memory),
1553
- skills: serializeEnabledList(options.skills),
1553
+ // SE22 — a SkillsResolver function isn't serializable; persist only the static form.
1554
+ skills: serializeEnabledList(typeof options.skills === "function" ? void 0 : options.skills),
1554
1555
  // Code-`Plugin` objects are closures and cannot be persisted (like custom
1555
1556
  // tools); only the named-enable settings form is serialized.
1556
1557
  plugins: serializeEnabledList(asPluginsSettings(options.plugins)),
@@ -1880,6 +1881,7 @@ function serializeCloud2(cloud) {
1880
1881
  return result;
1881
1882
  }
1882
1883
  function serializeSkills(skills) {
1884
+ if (typeof skills === "function") return void 0;
1883
1885
  if (skills?.enabled === void 0 || skills.enabled.length === 0) return void 0;
1884
1886
  return { enabled: [...skills.enabled] };
1885
1887
  }
@@ -3448,6 +3450,7 @@ var init_cloud_agent = __esm({
3448
3450
  function validateCloudToolParity(options) {
3449
3451
  if (options.cloud === void 0) return;
3450
3452
  rejectFunctionSystemPrompt(options);
3453
+ rejectFunctionSkills(options);
3451
3454
  rejectStdioMcpLocalPaths(options);
3452
3455
  }
3453
3456
  function rejectFunctionSystemPrompt(options) {
@@ -3458,6 +3461,14 @@ function rejectFunctionSystemPrompt(options) {
3458
3461
  );
3459
3462
  }
3460
3463
  }
3464
+ function rejectFunctionSkills(options) {
3465
+ if (typeof options.skills === "function") {
3466
+ throw new ConfigurationError(
3467
+ "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.",
3468
+ { code: "cloud_incompatible_function_resolver" }
3469
+ );
3470
+ }
3471
+ }
3461
3472
  function rejectStdioMcpLocalPaths(options) {
3462
3473
  if (options.mcpServers === void 0) return;
3463
3474
  for (const [name, config] of Object.entries(options.mcpServers)) {
@@ -5690,9 +5701,235 @@ var init_subagents_loader = __esm({
5690
5701
  }
5691
5702
  });
5692
5703
 
5704
+ // src/internal/runtime/skills/skill-frontmatter.ts
5705
+ function asString(v) {
5706
+ return typeof v === "string" ? v : void 0;
5707
+ }
5708
+ function toStringFields(raw) {
5709
+ const out = {};
5710
+ for (const [k, v] of Object.entries(raw)) out[k] = asString(v);
5711
+ return out;
5712
+ }
5713
+ function parseSkillFrontmatter(raw, fallbackName) {
5714
+ const fields = extractAndParseFrontmatter(raw, fallbackName);
5715
+ const name = resolveName(fields, fallbackName);
5716
+ ensureRequiredFields(fields, name);
5717
+ return buildFrontmatter(fields, name);
5718
+ }
5719
+ function stripSkillFrontmatter(raw) {
5720
+ const match = /^---\s*\n[\s\S]*?\n---\s*\n/.exec(raw);
5721
+ return (match === null ? raw : raw.slice(match[0].length)).trim();
5722
+ }
5723
+ function extractAndParseFrontmatter(raw, fallbackName) {
5724
+ const match = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(raw);
5725
+ if (match === null) {
5726
+ throw new ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {
5727
+ code: "missing_frontmatter"
5728
+ });
5729
+ }
5730
+ const frontmatter = match[1] ?? "";
5731
+ try {
5732
+ return toStringFields(parseSimpleYaml(frontmatter));
5733
+ } catch (cause) {
5734
+ const detail = cause instanceof Error ? cause.message : String(cause);
5735
+ throw new ConfigurationError(
5736
+ `Skill ${fallbackName} has malformed YAML frontmatter: ${detail}`,
5737
+ { code: "schema_invalid", cause }
5738
+ );
5739
+ }
5740
+ }
5741
+ function resolveName(fields, fallbackName) {
5742
+ if (hasContent(fields.name)) return fields.name;
5743
+ if (hasContent(fallbackName)) return fallbackName;
5744
+ throw new ConfigurationError("Skill at unknown path is missing required field: name", {
5745
+ code: "schema_invalid"
5746
+ });
5747
+ }
5748
+ function ensureRequiredFields(fields, name) {
5749
+ if (!hasContent(fields.description)) {
5750
+ throw new ConfigurationError(`Skill ${name} is missing required field: description`, {
5751
+ code: "schema_invalid"
5752
+ });
5753
+ }
5754
+ }
5755
+ function buildFrontmatter(fields, name) {
5756
+ const description = fields.description;
5757
+ if (description === void 0) {
5758
+ throw new ConfigurationError(`Skill ${name} missing description`, { code: "schema_invalid" });
5759
+ }
5760
+ const result = { name, description };
5761
+ if (hasContent(fields.category)) result.category = fields.category;
5762
+ const deps = parseDependencies(fields.dependencies);
5763
+ if (deps !== void 0) result.dependencies = deps;
5764
+ return result;
5765
+ }
5766
+ function parseDependencies(raw) {
5767
+ if (!hasContent(raw)) return void 0;
5768
+ const deps = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
5769
+ return deps.length > 0 ? deps : void 0;
5770
+ }
5771
+ function hasContent(value) {
5772
+ return value !== void 0 && value.trim().length > 0;
5773
+ }
5774
+ var init_skill_frontmatter = __esm({
5775
+ "src/internal/runtime/skills/skill-frontmatter.ts"() {
5776
+ init_errors();
5777
+ init_yaml_frontmatter();
5778
+ }
5779
+ });
5780
+ async function discoverSkills(dir, options) {
5781
+ let entries;
5782
+ try {
5783
+ entries = await readWorkspaceDir(dir, "skills_read_error", "skills directory");
5784
+ } catch {
5785
+ return [];
5786
+ }
5787
+ const skills = [];
5788
+ for (const entry of entries) {
5789
+ if (!entry.isDirectory()) continue;
5790
+ let skillDir;
5791
+ try {
5792
+ skillDir = safePathJoin(dir, entry.name);
5793
+ assertNoSymlinkEscape(skillDir, dir);
5794
+ } catch {
5795
+ continue;
5796
+ }
5797
+ const skillPath = join(skillDir, "SKILL.md");
5798
+ let raw;
5799
+ try {
5800
+ raw = await readFile(skillPath, "utf8");
5801
+ } catch {
5802
+ continue;
5803
+ }
5804
+ const skill = tryParseSkill(raw, entry.name, skillPath, options);
5805
+ if (skill !== void 0) skills.push(skill);
5806
+ }
5807
+ return skills;
5808
+ }
5809
+ function tryParseSkill(raw, fallbackName, source, options) {
5810
+ try {
5811
+ const frontmatter = parseSkillFrontmatter(raw, fallbackName);
5812
+ const skill = {
5813
+ name: frontmatter.name,
5814
+ description: frontmatter.description,
5815
+ source
5816
+ };
5817
+ if (frontmatter.category !== void 0) skill.category = frontmatter.category;
5818
+ if (frontmatter.dependencies !== void 0) skill.dependencies = frontmatter.dependencies;
5819
+ return skill;
5820
+ } catch (cause) {
5821
+ if (cause instanceof ConfigurationError) {
5822
+ options?.onInvalidSkill?.({
5823
+ name: fallbackName,
5824
+ source,
5825
+ code: cause.code ?? "unknown",
5826
+ message: cause.message
5827
+ });
5828
+ return void 0;
5829
+ }
5830
+ throw cause;
5831
+ }
5832
+ }
5833
+ var init_discover_skills = __esm({
5834
+ "src/internal/runtime/skills/discover-skills.ts"() {
5835
+ init_errors();
5836
+ init_path_guard();
5837
+ init_workspace_dir();
5838
+ init_skill_frontmatter();
5839
+ }
5840
+ });
5841
+ var SkillsManager;
5842
+ var init_skills_manager = __esm({
5843
+ "src/internal/runtime/skills/skills-manager.ts"() {
5844
+ init_discover_skills();
5845
+ init_skill_frontmatter();
5846
+ SkillsManager = class {
5847
+ constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
5848
+ this.cwd = cwd;
5849
+ this.settingSourcesIncludeProject = settingSourcesIncludeProject;
5850
+ this.skillsDir = skillsDir;
5851
+ this.inline = inline;
5852
+ }
5853
+ cwd;
5854
+ settingSourcesIncludeProject;
5855
+ skillsDir;
5856
+ inline;
5857
+ skills = [];
5858
+ async initialize() {
5859
+ if (!this.settingSourcesIncludeProject) {
5860
+ this.skills = this.mergeInline([]);
5861
+ return;
5862
+ }
5863
+ await this.refresh();
5864
+ }
5865
+ async refresh() {
5866
+ const skillsRoot = this.skillsDir ?? join(this.cwd, ".theokit", "skills");
5867
+ const discovered = await discoverSkills(skillsRoot, {
5868
+ onInvalidSkill: (info) => {
5869
+ process.stderr.write(
5870
+ `[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
5871
+ `
5872
+ );
5873
+ }
5874
+ });
5875
+ this.skills = this.mergeInline(discovered);
5876
+ }
5877
+ /** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
5878
+ mergeInline(discovered) {
5879
+ if (this.inline === void 0 || this.inline.length === 0) return discovered;
5880
+ const inlineNames = new Set(this.inline.map((s) => s.name));
5881
+ return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
5882
+ }
5883
+ list() {
5884
+ return Promise.resolve(this.skills);
5885
+ }
5886
+ /**
5887
+ * SE20 — resolve a skill by name INCLUDING its body. Inline (`createSkill`)
5888
+ * skills carry `instructions` on the object; filesystem skills read the body
5889
+ * from their `source` SKILL.md (frontmatter stripped). `undefined` when no
5890
+ * enabled skill matches (malformed skills were already excluded at discovery).
5891
+ */
5892
+ async get(name) {
5893
+ const skill = this.skills.find((s) => s.name === name);
5894
+ if (skill === void 0) return void 0;
5895
+ const instructions = typeof skill.instructions === "string" ? skill.instructions : stripSkillFrontmatter(await readFile(skill.source, "utf8"));
5896
+ const references = skill.references;
5897
+ return {
5898
+ name: skill.name,
5899
+ description: skill.description,
5900
+ instructions,
5901
+ ...references !== void 0 ? { references } : {}
5902
+ };
5903
+ }
5904
+ };
5905
+ }
5906
+ });
5907
+
5693
5908
  // src/internal/runtime/system-prompt/local-assembly.ts
5694
- async function buildSystemPromptContext(inputs, userText, memoryFacts) {
5695
- const skills = inputs.skillsManager !== void 0 ? await inputs.skillsManager.list() : [];
5909
+ async function resolveSendSkills(inputs, userText, memoryFacts) {
5910
+ const skills = inputs.options.skills;
5911
+ if (typeof skills !== "function") {
5912
+ return { manager: inputs.skillsManager, autoInject: skills?.autoInject ?? true };
5913
+ }
5914
+ const settings = await skills({
5915
+ agentId: inputs.agentId,
5916
+ cwd: inputs.workspaceCwd,
5917
+ model: inputs.model,
5918
+ userMessage: userText,
5919
+ memory: memoryFacts.map((fact) => ({ text: fact.text }))
5920
+ });
5921
+ const manager = new SkillsManager(
5922
+ inputs.workspaceCwd,
5923
+ settings.enabled,
5924
+ inputs.settingSourcesIncludeProject,
5925
+ settings.skillsDir,
5926
+ settings.inline
5927
+ );
5928
+ await manager.initialize();
5929
+ return { manager, autoInject: settings.autoInject ?? true };
5930
+ }
5931
+ async function buildSystemPromptContext(inputs, userText, memoryFacts, manager = inputs.skillsManager) {
5932
+ const skills = manager !== void 0 ? await manager.list() : [];
5696
5933
  return {
5697
5934
  agentId: inputs.agentId,
5698
5935
  cwd: inputs.workspaceCwd,
@@ -5703,10 +5940,11 @@ async function buildSystemPromptContext(inputs, userText, memoryFacts) {
5703
5940
  };
5704
5941
  }
5705
5942
  async function buildAssemblyContext(inputs, userText, baseSystemPrompt, memoryFacts, activeMemorySummary) {
5706
- const baseCtx = await buildSystemPromptContext(inputs, userText, memoryFacts);
5943
+ const resolved = await resolveSendSkills(inputs, userText, memoryFacts);
5944
+ const baseCtx = await buildSystemPromptContext(inputs, userText, memoryFacts, resolved.manager);
5707
5945
  const assemblyCtx = {
5708
5946
  ...baseCtx,
5709
- skillsAutoInject: inputs.options.skills?.autoInject ?? true,
5947
+ skillsAutoInject: resolved.autoInject,
5710
5948
  memoryAutoInject: inputs.options.memory?.autoInject ?? true
5711
5949
  };
5712
5950
  if (baseSystemPrompt !== void 0) assemblyCtx.baseSystemPrompt = baseSystemPrompt;
@@ -5732,6 +5970,7 @@ async function assembleSystemPromptForSend(inputs, userText, baseSystemPrompt, m
5732
5970
  }
5733
5971
  var init_local_assembly = __esm({
5734
5972
  "src/internal/runtime/system-prompt/local-assembly.ts"() {
5973
+ init_skills_manager();
5735
5974
  }
5736
5975
  });
5737
5976
 
@@ -7077,187 +7316,6 @@ var init_plugins_manager = __esm({
7077
7316
  }
7078
7317
  });
7079
7318
 
7080
- // src/internal/runtime/skills/skill-frontmatter.ts
7081
- function asString(v) {
7082
- return typeof v === "string" ? v : void 0;
7083
- }
7084
- function toStringFields(raw) {
7085
- const out = {};
7086
- for (const [k, v] of Object.entries(raw)) out[k] = asString(v);
7087
- return out;
7088
- }
7089
- function parseSkillFrontmatter(raw, fallbackName) {
7090
- const fields = extractAndParseFrontmatter(raw, fallbackName);
7091
- const name = resolveName(fields, fallbackName);
7092
- ensureRequiredFields(fields, name);
7093
- return buildFrontmatter(fields, name);
7094
- }
7095
- function extractAndParseFrontmatter(raw, fallbackName) {
7096
- const match = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(raw);
7097
- if (match === null) {
7098
- throw new ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {
7099
- code: "missing_frontmatter"
7100
- });
7101
- }
7102
- const frontmatter = match[1] ?? "";
7103
- try {
7104
- return toStringFields(parseSimpleYaml(frontmatter));
7105
- } catch (cause) {
7106
- const detail = cause instanceof Error ? cause.message : String(cause);
7107
- throw new ConfigurationError(
7108
- `Skill ${fallbackName} has malformed YAML frontmatter: ${detail}`,
7109
- { code: "schema_invalid", cause }
7110
- );
7111
- }
7112
- }
7113
- function resolveName(fields, fallbackName) {
7114
- if (hasContent(fields.name)) return fields.name;
7115
- if (hasContent(fallbackName)) return fallbackName;
7116
- throw new ConfigurationError("Skill at unknown path is missing required field: name", {
7117
- code: "schema_invalid"
7118
- });
7119
- }
7120
- function ensureRequiredFields(fields, name) {
7121
- if (!hasContent(fields.description)) {
7122
- throw new ConfigurationError(`Skill ${name} is missing required field: description`, {
7123
- code: "schema_invalid"
7124
- });
7125
- }
7126
- }
7127
- function buildFrontmatter(fields, name) {
7128
- const description = fields.description;
7129
- if (description === void 0) {
7130
- throw new ConfigurationError(`Skill ${name} missing description`, { code: "schema_invalid" });
7131
- }
7132
- const result = { name, description };
7133
- if (hasContent(fields.category)) result.category = fields.category;
7134
- const deps = parseDependencies(fields.dependencies);
7135
- if (deps !== void 0) result.dependencies = deps;
7136
- return result;
7137
- }
7138
- function parseDependencies(raw) {
7139
- if (!hasContent(raw)) return void 0;
7140
- const deps = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
7141
- return deps.length > 0 ? deps : void 0;
7142
- }
7143
- function hasContent(value) {
7144
- return value !== void 0 && value.trim().length > 0;
7145
- }
7146
- var init_skill_frontmatter = __esm({
7147
- "src/internal/runtime/skills/skill-frontmatter.ts"() {
7148
- init_errors();
7149
- init_yaml_frontmatter();
7150
- }
7151
- });
7152
- async function discoverSkills(dir, options) {
7153
- let entries;
7154
- try {
7155
- entries = await readWorkspaceDir(dir, "skills_read_error", "skills directory");
7156
- } catch {
7157
- return [];
7158
- }
7159
- const skills = [];
7160
- for (const entry of entries) {
7161
- if (!entry.isDirectory()) continue;
7162
- let skillDir;
7163
- try {
7164
- skillDir = safePathJoin(dir, entry.name);
7165
- assertNoSymlinkEscape(skillDir, dir);
7166
- } catch {
7167
- continue;
7168
- }
7169
- const skillPath = join(skillDir, "SKILL.md");
7170
- let raw;
7171
- try {
7172
- raw = await readFile(skillPath, "utf8");
7173
- } catch {
7174
- continue;
7175
- }
7176
- const skill = tryParseSkill(raw, entry.name, skillPath, options);
7177
- if (skill !== void 0) skills.push(skill);
7178
- }
7179
- return skills;
7180
- }
7181
- function tryParseSkill(raw, fallbackName, source, options) {
7182
- try {
7183
- const frontmatter = parseSkillFrontmatter(raw, fallbackName);
7184
- const skill = {
7185
- name: frontmatter.name,
7186
- description: frontmatter.description,
7187
- source
7188
- };
7189
- if (frontmatter.category !== void 0) skill.category = frontmatter.category;
7190
- if (frontmatter.dependencies !== void 0) skill.dependencies = frontmatter.dependencies;
7191
- return skill;
7192
- } catch (cause) {
7193
- if (cause instanceof ConfigurationError) {
7194
- options?.onInvalidSkill?.({
7195
- name: fallbackName,
7196
- source,
7197
- code: cause.code ?? "unknown",
7198
- message: cause.message
7199
- });
7200
- return void 0;
7201
- }
7202
- throw cause;
7203
- }
7204
- }
7205
- var init_discover_skills = __esm({
7206
- "src/internal/runtime/skills/discover-skills.ts"() {
7207
- init_errors();
7208
- init_path_guard();
7209
- init_workspace_dir();
7210
- init_skill_frontmatter();
7211
- }
7212
- });
7213
- var SkillsManager;
7214
- var init_skills_manager = __esm({
7215
- "src/internal/runtime/skills/skills-manager.ts"() {
7216
- init_discover_skills();
7217
- SkillsManager = class {
7218
- constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
7219
- this.cwd = cwd;
7220
- this.settingSourcesIncludeProject = settingSourcesIncludeProject;
7221
- this.skillsDir = skillsDir;
7222
- this.inline = inline;
7223
- }
7224
- cwd;
7225
- settingSourcesIncludeProject;
7226
- skillsDir;
7227
- inline;
7228
- skills = [];
7229
- async initialize() {
7230
- if (!this.settingSourcesIncludeProject) {
7231
- this.skills = this.mergeInline([]);
7232
- return;
7233
- }
7234
- await this.refresh();
7235
- }
7236
- async refresh() {
7237
- const skillsRoot = this.skillsDir ?? join(this.cwd, ".theokit", "skills");
7238
- const discovered = await discoverSkills(skillsRoot, {
7239
- onInvalidSkill: (info) => {
7240
- process.stderr.write(
7241
- `[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
7242
- `
7243
- );
7244
- }
7245
- });
7246
- this.skills = this.mergeInline(discovered);
7247
- }
7248
- /** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
7249
- mergeInline(discovered) {
7250
- if (this.inline === void 0 || this.inline.length === 0) return discovered;
7251
- const inlineNames = new Set(this.inline.map((s) => s.name));
7252
- return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
7253
- }
7254
- list() {
7255
- return Promise.resolve(this.skills);
7256
- }
7257
- };
7258
- }
7259
- });
7260
-
7261
7319
  // src/internal/runtime/local-agent/local-agent-bootstrap.ts
7262
7320
  function registerLocalAgent(args) {
7263
7321
  registerAgent({
@@ -7293,16 +7351,23 @@ function bootstrapSubmanagers(args) {
7293
7351
  );
7294
7352
  }
7295
7353
  if (args.options.skills !== void 0 || args.settingSourcesIncludeProject) {
7354
+ const staticSkills = typeof args.options.skills === "function" ? void 0 : args.options.skills;
7296
7355
  out.skillsManager = new SkillsManager(
7297
7356
  args.workspaceCwd,
7298
- args.options.skills?.enabled,
7357
+ staticSkills?.enabled,
7299
7358
  args.settingSourcesIncludeProject,
7300
7359
  // M22 — custom skills directory + inline (code-defined) skills.
7301
- args.options.skills?.skillsDir,
7302
- args.options.skills?.inline
7360
+ staticSkills?.skillsDir,
7361
+ staticSkills?.inline
7303
7362
  );
7304
7363
  const localSkills = out.skillsManager;
7305
- out.skills = { list: () => localSkills.list() };
7364
+ out.skills = {
7365
+ // Project to the public shape (name + description only). Inline skills carry
7366
+ // their body + references on the object; `list()` must never leak them —
7367
+ // the body is reachable exclusively through `get()`.
7368
+ list: async () => (await localSkills.list()).map((s) => ({ name: s.name, description: s.description })),
7369
+ get: (name) => localSkills.get(name)
7370
+ };
7306
7371
  }
7307
7372
  if (args.options.plugins !== void 0 || args.settingSourcesIncludePlugins) {
7308
7373
  out.pluginsManager = new PluginsManager(
@@ -17232,7 +17297,7 @@ var init_local_agent = __esm({
17232
17297
  }
17233
17298
  // biome-ignore format: G8 budget — thin accessor for the assembly inputs.
17234
17299
  assemblyInputs() {
17235
- return { agentId: this.agentId, workspaceCwd: this.workspaceCwd, model: this.model, options: this.options, context: this.context, skillsManager: this.skillsManager, systemPromptPipeline: this.systemPromptPipeline };
17300
+ 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 };
17236
17301
  }
17237
17302
  async resolveSystemPrompt(userText, options, memoryFacts) {
17238
17303
  const base = await resolveSystemPromptForSend(