@theokit/sdk 2.24.0 → 2.26.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.
Files changed (42) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/dist/a2a/index.cjs +464 -195
  3. package/dist/a2a/index.cjs.map +1 -1
  4. package/dist/a2a/index.js +464 -195
  5. package/dist/a2a/index.js.map +1 -1
  6. package/dist/create-skill.d.ts +8 -0
  7. package/dist/{cron-vjod0qVQ.d.ts → cron-BR1NCSk1.d.cts} +77 -4
  8. package/dist/{cron-Bd2oRD7A.d.cts → cron-DgEQCJ2i.d.ts} +77 -4
  9. package/dist/cron.cjs +430 -184
  10. package/dist/cron.cjs.map +1 -1
  11. package/dist/cron.d.cts +2 -2
  12. package/dist/cron.d.ts +2 -2
  13. package/dist/cron.js +430 -184
  14. package/dist/cron.js.map +1 -1
  15. package/dist/{errors-DRS-kqOK.d.ts → errors-CbY3pxY7.d.ts} +1 -1
  16. package/dist/{errors-DIKBXffg.d.cts → errors-DLMNb4Ka.d.cts} +1 -1
  17. package/dist/errors.d.cts +2 -2
  18. package/dist/eval.cjs +430 -184
  19. package/dist/eval.cjs.map +1 -1
  20. package/dist/eval.js +430 -184
  21. package/dist/eval.js.map +1 -1
  22. package/dist/index.cjs +523 -190
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +93 -7
  25. package/dist/index.d.ts +93 -7
  26. package/dist/index.js +520 -191
  27. package/dist/index.js.map +1 -1
  28. package/dist/internal/runtime/local-agent/local-agent-bootstrap.d.ts +2 -4
  29. package/dist/internal/runtime/processors/run-processors.d.ts +10 -0
  30. package/dist/internal/runtime/processors/tripwire-run.d.ts +16 -0
  31. package/dist/internal/runtime/processors/wrap-output-run.d.ts +18 -0
  32. package/dist/internal/runtime/skills/skill-frontmatter.d.ts +6 -0
  33. package/dist/{run-Cr0C6cOM.d.cts → run-CdWiihyU.d.cts} +109 -2
  34. package/dist/{run-Cr0C6cOM.d.ts → run-CdWiihyU.d.ts} +109 -2
  35. package/dist/skills.cjs.map +1 -1
  36. package/dist/skills.js.map +1 -1
  37. package/dist/types/agent.d.ts +67 -2
  38. package/dist/types/index.d.ts +1 -0
  39. package/dist/types/processors.d.ts +84 -0
  40. package/dist/types/run-events.d.ts +11 -1
  41. package/dist/types/run.d.ts +12 -0
  42. package/package.json +1 -1
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,8 +3450,19 @@ 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);
3454
+ rejectProcessors(options);
3451
3455
  rejectStdioMcpLocalPaths(options);
3452
3456
  }
3457
+ function rejectProcessors(options) {
3458
+ const hasProcessors = (options.inputProcessors?.length ?? 0) > 0 || (options.outputProcessors?.length ?? 0) > 0;
3459
+ if (hasProcessors) {
3460
+ throw new ConfigurationError(
3461
+ "Cloud agents can't run guardrail processors \u2014 a Processor carries function handlers that don't survive serialization to PaaS. Run processors on a local agent, or move the guardrail into a server-side gateway in front of TheoCloud.",
3462
+ { code: "cloud_incompatible_function_resolver" }
3463
+ );
3464
+ }
3465
+ }
3453
3466
  function rejectFunctionSystemPrompt(options) {
3454
3467
  if (typeof options.systemPrompt === "function") {
3455
3468
  throw new ConfigurationError(
@@ -3458,6 +3471,14 @@ function rejectFunctionSystemPrompt(options) {
3458
3471
  );
3459
3472
  }
3460
3473
  }
3474
+ function rejectFunctionSkills(options) {
3475
+ if (typeof options.skills === "function") {
3476
+ throw new ConfigurationError(
3477
+ "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.",
3478
+ { code: "cloud_incompatible_function_resolver" }
3479
+ );
3480
+ }
3481
+ }
3461
3482
  function rejectStdioMcpLocalPaths(options) {
3462
3483
  if (options.mcpServers === void 0) return;
3463
3484
  for (const [name, config] of Object.entries(options.mcpServers)) {
@@ -5690,9 +5711,235 @@ var init_subagents_loader = __esm({
5690
5711
  }
5691
5712
  });
5692
5713
 
5714
+ // src/internal/runtime/skills/skill-frontmatter.ts
5715
+ function asString(v) {
5716
+ return typeof v === "string" ? v : void 0;
5717
+ }
5718
+ function toStringFields(raw) {
5719
+ const out = {};
5720
+ for (const [k, v] of Object.entries(raw)) out[k] = asString(v);
5721
+ return out;
5722
+ }
5723
+ function parseSkillFrontmatter(raw, fallbackName) {
5724
+ const fields = extractAndParseFrontmatter(raw, fallbackName);
5725
+ const name = resolveName(fields, fallbackName);
5726
+ ensureRequiredFields(fields, name);
5727
+ return buildFrontmatter(fields, name);
5728
+ }
5729
+ function stripSkillFrontmatter(raw) {
5730
+ const match = /^---\s*\n[\s\S]*?\n---\s*\n/.exec(raw);
5731
+ return (match === null ? raw : raw.slice(match[0].length)).trim();
5732
+ }
5733
+ function extractAndParseFrontmatter(raw, fallbackName) {
5734
+ const match = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(raw);
5735
+ if (match === null) {
5736
+ throw new ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {
5737
+ code: "missing_frontmatter"
5738
+ });
5739
+ }
5740
+ const frontmatter = match[1] ?? "";
5741
+ try {
5742
+ return toStringFields(parseSimpleYaml(frontmatter));
5743
+ } catch (cause) {
5744
+ const detail = cause instanceof Error ? cause.message : String(cause);
5745
+ throw new ConfigurationError(
5746
+ `Skill ${fallbackName} has malformed YAML frontmatter: ${detail}`,
5747
+ { code: "schema_invalid", cause }
5748
+ );
5749
+ }
5750
+ }
5751
+ function resolveName(fields, fallbackName) {
5752
+ if (hasContent(fields.name)) return fields.name;
5753
+ if (hasContent(fallbackName)) return fallbackName;
5754
+ throw new ConfigurationError("Skill at unknown path is missing required field: name", {
5755
+ code: "schema_invalid"
5756
+ });
5757
+ }
5758
+ function ensureRequiredFields(fields, name) {
5759
+ if (!hasContent(fields.description)) {
5760
+ throw new ConfigurationError(`Skill ${name} is missing required field: description`, {
5761
+ code: "schema_invalid"
5762
+ });
5763
+ }
5764
+ }
5765
+ function buildFrontmatter(fields, name) {
5766
+ const description = fields.description;
5767
+ if (description === void 0) {
5768
+ throw new ConfigurationError(`Skill ${name} missing description`, { code: "schema_invalid" });
5769
+ }
5770
+ const result = { name, description };
5771
+ if (hasContent(fields.category)) result.category = fields.category;
5772
+ const deps = parseDependencies(fields.dependencies);
5773
+ if (deps !== void 0) result.dependencies = deps;
5774
+ return result;
5775
+ }
5776
+ function parseDependencies(raw) {
5777
+ if (!hasContent(raw)) return void 0;
5778
+ const deps = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
5779
+ return deps.length > 0 ? deps : void 0;
5780
+ }
5781
+ function hasContent(value) {
5782
+ return value !== void 0 && value.trim().length > 0;
5783
+ }
5784
+ var init_skill_frontmatter = __esm({
5785
+ "src/internal/runtime/skills/skill-frontmatter.ts"() {
5786
+ init_errors();
5787
+ init_yaml_frontmatter();
5788
+ }
5789
+ });
5790
+ async function discoverSkills(dir, options) {
5791
+ let entries;
5792
+ try {
5793
+ entries = await readWorkspaceDir(dir, "skills_read_error", "skills directory");
5794
+ } catch {
5795
+ return [];
5796
+ }
5797
+ const skills = [];
5798
+ for (const entry of entries) {
5799
+ if (!entry.isDirectory()) continue;
5800
+ let skillDir;
5801
+ try {
5802
+ skillDir = safePathJoin(dir, entry.name);
5803
+ assertNoSymlinkEscape(skillDir, dir);
5804
+ } catch {
5805
+ continue;
5806
+ }
5807
+ const skillPath = join(skillDir, "SKILL.md");
5808
+ let raw;
5809
+ try {
5810
+ raw = await readFile(skillPath, "utf8");
5811
+ } catch {
5812
+ continue;
5813
+ }
5814
+ const skill = tryParseSkill(raw, entry.name, skillPath, options);
5815
+ if (skill !== void 0) skills.push(skill);
5816
+ }
5817
+ return skills;
5818
+ }
5819
+ function tryParseSkill(raw, fallbackName, source, options) {
5820
+ try {
5821
+ const frontmatter = parseSkillFrontmatter(raw, fallbackName);
5822
+ const skill = {
5823
+ name: frontmatter.name,
5824
+ description: frontmatter.description,
5825
+ source
5826
+ };
5827
+ if (frontmatter.category !== void 0) skill.category = frontmatter.category;
5828
+ if (frontmatter.dependencies !== void 0) skill.dependencies = frontmatter.dependencies;
5829
+ return skill;
5830
+ } catch (cause) {
5831
+ if (cause instanceof ConfigurationError) {
5832
+ options?.onInvalidSkill?.({
5833
+ name: fallbackName,
5834
+ source,
5835
+ code: cause.code ?? "unknown",
5836
+ message: cause.message
5837
+ });
5838
+ return void 0;
5839
+ }
5840
+ throw cause;
5841
+ }
5842
+ }
5843
+ var init_discover_skills = __esm({
5844
+ "src/internal/runtime/skills/discover-skills.ts"() {
5845
+ init_errors();
5846
+ init_path_guard();
5847
+ init_workspace_dir();
5848
+ init_skill_frontmatter();
5849
+ }
5850
+ });
5851
+ var SkillsManager;
5852
+ var init_skills_manager = __esm({
5853
+ "src/internal/runtime/skills/skills-manager.ts"() {
5854
+ init_discover_skills();
5855
+ init_skill_frontmatter();
5856
+ SkillsManager = class {
5857
+ constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
5858
+ this.cwd = cwd;
5859
+ this.settingSourcesIncludeProject = settingSourcesIncludeProject;
5860
+ this.skillsDir = skillsDir;
5861
+ this.inline = inline;
5862
+ }
5863
+ cwd;
5864
+ settingSourcesIncludeProject;
5865
+ skillsDir;
5866
+ inline;
5867
+ skills = [];
5868
+ async initialize() {
5869
+ if (!this.settingSourcesIncludeProject) {
5870
+ this.skills = this.mergeInline([]);
5871
+ return;
5872
+ }
5873
+ await this.refresh();
5874
+ }
5875
+ async refresh() {
5876
+ const skillsRoot = this.skillsDir ?? join(this.cwd, ".theokit", "skills");
5877
+ const discovered = await discoverSkills(skillsRoot, {
5878
+ onInvalidSkill: (info) => {
5879
+ process.stderr.write(
5880
+ `[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
5881
+ `
5882
+ );
5883
+ }
5884
+ });
5885
+ this.skills = this.mergeInline(discovered);
5886
+ }
5887
+ /** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
5888
+ mergeInline(discovered) {
5889
+ if (this.inline === void 0 || this.inline.length === 0) return discovered;
5890
+ const inlineNames = new Set(this.inline.map((s) => s.name));
5891
+ return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
5892
+ }
5893
+ list() {
5894
+ return Promise.resolve(this.skills);
5895
+ }
5896
+ /**
5897
+ * SE20 — resolve a skill by name INCLUDING its body. Inline (`createSkill`)
5898
+ * skills carry `instructions` on the object; filesystem skills read the body
5899
+ * from their `source` SKILL.md (frontmatter stripped). `undefined` when no
5900
+ * enabled skill matches (malformed skills were already excluded at discovery).
5901
+ */
5902
+ async get(name) {
5903
+ const skill = this.skills.find((s) => s.name === name);
5904
+ if (skill === void 0) return void 0;
5905
+ const instructions = typeof skill.instructions === "string" ? skill.instructions : stripSkillFrontmatter(await readFile(skill.source, "utf8"));
5906
+ const references = skill.references;
5907
+ return {
5908
+ name: skill.name,
5909
+ description: skill.description,
5910
+ instructions,
5911
+ ...references !== void 0 ? { references } : {}
5912
+ };
5913
+ }
5914
+ };
5915
+ }
5916
+ });
5917
+
5693
5918
  // 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() : [];
5919
+ async function resolveSendSkills(inputs, userText, memoryFacts) {
5920
+ const skills = inputs.options.skills;
5921
+ if (typeof skills !== "function") {
5922
+ return { manager: inputs.skillsManager, autoInject: skills?.autoInject ?? true };
5923
+ }
5924
+ const settings = await skills({
5925
+ agentId: inputs.agentId,
5926
+ cwd: inputs.workspaceCwd,
5927
+ model: inputs.model,
5928
+ userMessage: userText,
5929
+ memory: memoryFacts.map((fact) => ({ text: fact.text }))
5930
+ });
5931
+ const manager = new SkillsManager(
5932
+ inputs.workspaceCwd,
5933
+ settings.enabled,
5934
+ inputs.settingSourcesIncludeProject,
5935
+ settings.skillsDir,
5936
+ settings.inline
5937
+ );
5938
+ await manager.initialize();
5939
+ return { manager, autoInject: settings.autoInject ?? true };
5940
+ }
5941
+ async function buildSystemPromptContext(inputs, userText, memoryFacts, manager = inputs.skillsManager) {
5942
+ const skills = manager !== void 0 ? await manager.list() : [];
5696
5943
  return {
5697
5944
  agentId: inputs.agentId,
5698
5945
  cwd: inputs.workspaceCwd,
@@ -5703,10 +5950,11 @@ async function buildSystemPromptContext(inputs, userText, memoryFacts) {
5703
5950
  };
5704
5951
  }
5705
5952
  async function buildAssemblyContext(inputs, userText, baseSystemPrompt, memoryFacts, activeMemorySummary) {
5706
- const baseCtx = await buildSystemPromptContext(inputs, userText, memoryFacts);
5953
+ const resolved = await resolveSendSkills(inputs, userText, memoryFacts);
5954
+ const baseCtx = await buildSystemPromptContext(inputs, userText, memoryFacts, resolved.manager);
5707
5955
  const assemblyCtx = {
5708
5956
  ...baseCtx,
5709
- skillsAutoInject: inputs.options.skills?.autoInject ?? true,
5957
+ skillsAutoInject: resolved.autoInject,
5710
5958
  memoryAutoInject: inputs.options.memory?.autoInject ?? true
5711
5959
  };
5712
5960
  if (baseSystemPrompt !== void 0) assemblyCtx.baseSystemPrompt = baseSystemPrompt;
@@ -5732,6 +5980,7 @@ async function assembleSystemPromptForSend(inputs, userText, baseSystemPrompt, m
5732
5980
  }
5733
5981
  var init_local_assembly = __esm({
5734
5982
  "src/internal/runtime/system-prompt/local-assembly.ts"() {
5983
+ init_skills_manager();
5735
5984
  }
5736
5985
  });
5737
5986
 
@@ -7077,187 +7326,6 @@ var init_plugins_manager = __esm({
7077
7326
  }
7078
7327
  });
7079
7328
 
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
7329
  // src/internal/runtime/local-agent/local-agent-bootstrap.ts
7262
7330
  function registerLocalAgent(args) {
7263
7331
  registerAgent({
@@ -7293,16 +7361,23 @@ function bootstrapSubmanagers(args) {
7293
7361
  );
7294
7362
  }
7295
7363
  if (args.options.skills !== void 0 || args.settingSourcesIncludeProject) {
7364
+ const staticSkills = typeof args.options.skills === "function" ? void 0 : args.options.skills;
7296
7365
  out.skillsManager = new SkillsManager(
7297
7366
  args.workspaceCwd,
7298
- args.options.skills?.enabled,
7367
+ staticSkills?.enabled,
7299
7368
  args.settingSourcesIncludeProject,
7300
7369
  // M22 — custom skills directory + inline (code-defined) skills.
7301
- args.options.skills?.skillsDir,
7302
- args.options.skills?.inline
7370
+ staticSkills?.skillsDir,
7371
+ staticSkills?.inline
7303
7372
  );
7304
7373
  const localSkills = out.skillsManager;
7305
- out.skills = { list: () => localSkills.list() };
7374
+ out.skills = {
7375
+ // Project to the public shape (name + description only). Inline skills carry
7376
+ // their body + references on the object; `list()` must never leak them —
7377
+ // the body is reachable exclusively through `get()`.
7378
+ list: async () => (await localSkills.list()).map((s) => ({ name: s.name, description: s.description })),
7379
+ get: (name) => localSkills.get(name)
7380
+ };
7306
7381
  }
7307
7382
  if (args.options.plugins !== void 0 || args.settingSourcesIncludePlugins) {
7308
7383
  out.pluginsManager = new PluginsManager(
@@ -16288,6 +16363,162 @@ var init_abort_utils = __esm({
16288
16363
  }
16289
16364
  });
16290
16365
 
16366
+ // src/internal/runtime/processors/run-processors.ts
16367
+ function fireViolation(processor, violation) {
16368
+ try {
16369
+ processor.onViolation?.(violation);
16370
+ } catch {
16371
+ }
16372
+ }
16373
+ function controlsFor(processor) {
16374
+ return {
16375
+ abort(reason) {
16376
+ throw new ProcessorAbort(processor.id, reason);
16377
+ },
16378
+ warn(message, detail) {
16379
+ fireViolation(processor, {
16380
+ processorId: processor.id,
16381
+ message,
16382
+ ...detail !== void 0 ? { detail } : {}
16383
+ });
16384
+ }
16385
+ };
16386
+ }
16387
+ function selectHandler(processor, phase) {
16388
+ if (phase === "input") {
16389
+ return processor.processInput ? { kind: "input", fn: processor.processInput } : void 0;
16390
+ }
16391
+ return processor.processOutput ? { kind: "output", fn: processor.processOutput } : void 0;
16392
+ }
16393
+ function invokeHandler(handler, value, agentId, controls) {
16394
+ return handler.kind === "input" ? handler.fn({ message: value, agentId, ...controls }) : handler.fn({ text: value, agentId, ...controls });
16395
+ }
16396
+ async function runOneProcessor(processor, value, agentId, phase) {
16397
+ const handler = selectHandler(processor, phase);
16398
+ if (handler === void 0) return { value };
16399
+ try {
16400
+ const out = await invokeHandler(handler, value, agentId, controlsFor(processor));
16401
+ return { value: typeof out === "string" ? out : value };
16402
+ } catch (err) {
16403
+ if (!(err instanceof ProcessorAbort)) throw err;
16404
+ fireViolation(processor, { processorId: err.processorId, message: err.reason });
16405
+ return { tripwire: { reason: err.reason, processorId: err.processorId } };
16406
+ }
16407
+ }
16408
+ async function runPipeline(processors, initial, agentId, phase) {
16409
+ let value = initial;
16410
+ for (const processor of processors) {
16411
+ const step = await runOneProcessor(processor, value, agentId, phase);
16412
+ if ("tripwire" in step) return { kind: "tripwire", tripwire: step.tripwire };
16413
+ value = step.value;
16414
+ }
16415
+ return { kind: "ok", value };
16416
+ }
16417
+ function runInputProcessors(processors, message, agentId) {
16418
+ return runPipeline(processors, message, agentId, "input");
16419
+ }
16420
+ function runOutputProcessors(processors, text, agentId) {
16421
+ return runPipeline(processors, text, agentId, "output");
16422
+ }
16423
+ var ProcessorAbort;
16424
+ var init_run_processors = __esm({
16425
+ "src/internal/runtime/processors/run-processors.ts"() {
16426
+ ProcessorAbort = class {
16427
+ constructor(processorId, reason) {
16428
+ this.processorId = processorId;
16429
+ this.reason = reason;
16430
+ }
16431
+ processorId;
16432
+ reason;
16433
+ };
16434
+ }
16435
+ });
16436
+
16437
+ // src/internal/runtime/processors/tripwire-run.ts
16438
+ function emptyStream() {
16439
+ return {
16440
+ next: () => Promise.resolve({ done: true, value: void 0 }),
16441
+ return: () => Promise.resolve({ done: true, value: void 0 }),
16442
+ throw: (err) => Promise.reject(err),
16443
+ [Symbol.asyncIterator]() {
16444
+ return this;
16445
+ }
16446
+ };
16447
+ }
16448
+ function createTripwireRun(args) {
16449
+ const id = globalThis.crypto.randomUUID();
16450
+ const result = {
16451
+ id,
16452
+ status: "cancelled",
16453
+ tripwire: args.tripwire,
16454
+ ...args.model !== void 0 ? { model: args.model } : {}
16455
+ };
16456
+ const run = {
16457
+ id,
16458
+ agentId: args.agentId,
16459
+ status: "cancelled",
16460
+ ...args.model !== void 0 ? { model: args.model } : {},
16461
+ stream: () => emptyStream(),
16462
+ wait: () => Promise.resolve(result),
16463
+ cancel: () => Promise.resolve(),
16464
+ conversation: () => Promise.resolve([]),
16465
+ supports: (op) => SUPPORTED.has(op),
16466
+ unsupportedReason: (op) => SUPPORTED.has(op) ? void 0 : `operation "${op}" is not available on a tripwire run`,
16467
+ onDidChangeStatus: () => () => {
16468
+ }
16469
+ // already terminal — status never changes
16470
+ };
16471
+ registerRun(run);
16472
+ return run;
16473
+ }
16474
+ var SUPPORTED;
16475
+ var init_tripwire_run = __esm({
16476
+ "src/internal/runtime/processors/tripwire-run.ts"() {
16477
+ init_run_registry();
16478
+ SUPPORTED = /* @__PURE__ */ new Set([
16479
+ "stream",
16480
+ "wait",
16481
+ "cancel",
16482
+ "conversation"
16483
+ ]);
16484
+ }
16485
+ });
16486
+
16487
+ // src/internal/runtime/processors/wrap-output-run.ts
16488
+ function wrapRunWithOutputProcessors(args) {
16489
+ if (args.processors.length === 0) return args.run;
16490
+ const compute = async () => {
16491
+ const result = await args.run.wait();
16492
+ if (result.status !== "finished" || result.result === void 0) return result;
16493
+ const res = await runOutputProcessors(args.processors, result.result, args.agentId);
16494
+ if (res.kind === "ok") return { ...result, result: res.value };
16495
+ emitRunEvent(args.onRunEvent, {
16496
+ type: "tripwire",
16497
+ reason: res.tripwire.reason,
16498
+ processorId: res.tripwire.processorId
16499
+ });
16500
+ const { result: _suppressed, ...metadata } = result;
16501
+ return { ...metadata, status: "cancelled", tripwire: res.tripwire };
16502
+ };
16503
+ let processed;
16504
+ const wrappedWait = () => {
16505
+ processed ??= compute();
16506
+ return processed;
16507
+ };
16508
+ return new Proxy(args.run, {
16509
+ get(target, prop, receiver) {
16510
+ if (prop === "wait") return wrappedWait;
16511
+ return Reflect.get(target, prop, receiver);
16512
+ }
16513
+ });
16514
+ }
16515
+ var init_wrap_output_run = __esm({
16516
+ "src/internal/runtime/processors/wrap-output-run.ts"() {
16517
+ init_run_events();
16518
+ init_run_processors();
16519
+ }
16520
+ });
16521
+
16291
16522
  // src/internal/runtime/local-agent/local-agent-memory-hooks.ts
16292
16523
  async function applyPreUserSendHook(args) {
16293
16524
  const handlers = args.pluginManager.hooksFor("pre_user_send");
@@ -16340,11 +16571,38 @@ var init_local_agent_memory_hooks = __esm({
16340
16571
  });
16341
16572
 
16342
16573
  // src/internal/runtime/local-agent/local-agent-send.ts
16574
+ async function applyInputProcessors(inputs, message, rawUserText, options, sendModel) {
16575
+ const processors = inputs.options.inputProcessors;
16576
+ if (processors === void 0 || processors.length === 0) {
16577
+ return { userText: rawUserText, effectiveMessage: message };
16578
+ }
16579
+ const res = await runInputProcessors(processors, rawUserText, inputs.agentId);
16580
+ if (res.kind === "tripwire") {
16581
+ emitRunEvent(options.onRunEvent, {
16582
+ type: "tripwire",
16583
+ reason: res.tripwire.reason,
16584
+ processorId: res.tripwire.processorId
16585
+ });
16586
+ return {
16587
+ tripwireRun: createTripwireRun({
16588
+ agentId: inputs.agentId,
16589
+ tripwire: res.tripwire,
16590
+ model: sendModel
16591
+ })
16592
+ };
16593
+ }
16594
+ const effectiveMessage = typeof message === "string" ? res.value : { ...message, text: res.value };
16595
+ return { userText: res.value, effectiveMessage };
16596
+ }
16343
16597
  async function executeSendLocked(inputs, message, options) {
16344
16598
  if (inputs.disposed) throw new AgentDisposedError(inputs.agentId);
16345
16599
  await consumePending(inputs.agentId, inputs.invalidationPending, inputs.clearInvalidation, inputs.reload);
16346
- inputs.applyModelOverride(normalizeModel(options.model));
16347
- const userText = typeof message === "string" ? message : message.text;
16600
+ const sendModel = normalizeModel(options.model);
16601
+ inputs.applyModelOverride(sendModel);
16602
+ const rawUserText = typeof message === "string" ? message : message.text;
16603
+ const gated = await applyInputProcessors(inputs, message, rawUserText, options, sendModel);
16604
+ if ("tripwireRun" in gated) return gated.tripwireRun;
16605
+ const { userText, effectiveMessage } = gated;
16348
16606
  if (inputs.options.onBeforeSend !== void 0) {
16349
16607
  await inputs.options.onBeforeSend({
16350
16608
  conversationId: inputs.agentId,
@@ -16356,7 +16614,7 @@ async function executeSendLocked(inputs, message, options) {
16356
16614
  pluginManager: inputs.pluginManagerCode,
16357
16615
  agentId: inputs.agentId,
16358
16616
  options: inputs.options,
16359
- original: message,
16617
+ original: effectiveMessage,
16360
16618
  userText,
16361
16619
  sendOptions: options
16362
16620
  });
@@ -16394,11 +16652,18 @@ async function executeSendLocked(inputs, message, options) {
16394
16652
  memoryTools,
16395
16653
  effectiveMemoryProvider
16396
16654
  );
16655
+ const outputProcessors = inputs.options.outputProcessors;
16656
+ const processedRun = outputProcessors !== void 0 && outputProcessors.length > 0 ? wrapRunWithOutputProcessors({
16657
+ run,
16658
+ processors: outputProcessors,
16659
+ agentId: inputs.agentId,
16660
+ onRunEvent: options.onRunEvent
16661
+ }) : run;
16397
16662
  return wrapRunWithPostReplyHook({
16398
16663
  pluginManager: inputs.pluginManagerCode,
16399
16664
  agentId: inputs.agentId,
16400
16665
  options: inputs.options,
16401
- run,
16666
+ run: processedRun,
16402
16667
  userText
16403
16668
  });
16404
16669
  }
@@ -16409,10 +16674,14 @@ function readMemoryForSend(workspaceCwd, memoryConfig) {
16409
16674
  var init_local_agent_send = __esm({
16410
16675
  "src/internal/runtime/local-agent/local-agent-send.ts"() {
16411
16676
  init_errors();
16677
+ init_run_events();
16412
16678
  init_abort_utils();
16413
16679
  init_memory_path_selector();
16414
16680
  init_memory_store();
16415
16681
  init_model_selection();
16682
+ init_run_processors();
16683
+ init_tripwire_run();
16684
+ init_wrap_output_run();
16416
16685
  init_agent_session();
16417
16686
  init_safe_call();
16418
16687
  init_local_agent_invalidate();
@@ -17232,7 +17501,7 @@ var init_local_agent = __esm({
17232
17501
  }
17233
17502
  // biome-ignore format: G8 budget — thin accessor for the assembly inputs.
17234
17503
  assemblyInputs() {
17235
- return { agentId: this.agentId, workspaceCwd: this.workspaceCwd, model: this.model, options: this.options, context: this.context, skillsManager: this.skillsManager, systemPromptPipeline: this.systemPromptPipeline };
17504
+ 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
17505
  }
17237
17506
  async resolveSystemPrompt(userText, options, memoryFacts) {
17238
17507
  const base = await resolveSystemPromptForSend(