@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
@@ -1553,7 +1553,8 @@ function stripSecretsFromOptions(options) {
1553
1553
  local: serializeLocal(options.local),
1554
1554
  cloud: serializeCloud(options.cloud),
1555
1555
  memory: serializeMemory(options.memory),
1556
- skills: serializeEnabledList(options.skills),
1556
+ // SE22 — a SkillsResolver function isn't serializable; persist only the static form.
1557
+ skills: serializeEnabledList(typeof options.skills === "function" ? void 0 : options.skills),
1557
1558
  // Code-`Plugin` objects are closures and cannot be persisted (like custom
1558
1559
  // tools); only the named-enable settings form is serialized.
1559
1560
  plugins: serializeEnabledList(asPluginsSettings(options.plugins)),
@@ -1883,6 +1884,7 @@ function serializeCloud2(cloud) {
1883
1884
  return result;
1884
1885
  }
1885
1886
  function serializeSkills(skills) {
1887
+ if (typeof skills === "function") return void 0;
1886
1888
  if (skills?.enabled === void 0 || skills.enabled.length === 0) return void 0;
1887
1889
  return { enabled: [...skills.enabled] };
1888
1890
  }
@@ -3451,8 +3453,19 @@ var init_cloud_agent = __esm({
3451
3453
  function validateCloudToolParity(options) {
3452
3454
  if (options.cloud === void 0) return;
3453
3455
  rejectFunctionSystemPrompt(options);
3456
+ rejectFunctionSkills(options);
3457
+ rejectProcessors(options);
3454
3458
  rejectStdioMcpLocalPaths(options);
3455
3459
  }
3460
+ function rejectProcessors(options) {
3461
+ const hasProcessors = (options.inputProcessors?.length ?? 0) > 0 || (options.outputProcessors?.length ?? 0) > 0;
3462
+ if (hasProcessors) {
3463
+ throw new ConfigurationError(
3464
+ "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.",
3465
+ { code: "cloud_incompatible_function_resolver" }
3466
+ );
3467
+ }
3468
+ }
3456
3469
  function rejectFunctionSystemPrompt(options) {
3457
3470
  if (typeof options.systemPrompt === "function") {
3458
3471
  throw new ConfigurationError(
@@ -3461,6 +3474,14 @@ function rejectFunctionSystemPrompt(options) {
3461
3474
  );
3462
3475
  }
3463
3476
  }
3477
+ function rejectFunctionSkills(options) {
3478
+ if (typeof options.skills === "function") {
3479
+ throw new ConfigurationError(
3480
+ "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.",
3481
+ { code: "cloud_incompatible_function_resolver" }
3482
+ );
3483
+ }
3484
+ }
3464
3485
  function rejectStdioMcpLocalPaths(options) {
3465
3486
  if (options.mcpServers === void 0) return;
3466
3487
  for (const [name, config] of Object.entries(options.mcpServers)) {
@@ -5693,9 +5714,235 @@ var init_subagents_loader = __esm({
5693
5714
  }
5694
5715
  });
5695
5716
 
5717
+ // src/internal/runtime/skills/skill-frontmatter.ts
5718
+ function asString(v) {
5719
+ return typeof v === "string" ? v : void 0;
5720
+ }
5721
+ function toStringFields(raw) {
5722
+ const out = {};
5723
+ for (const [k, v] of Object.entries(raw)) out[k] = asString(v);
5724
+ return out;
5725
+ }
5726
+ function parseSkillFrontmatter(raw, fallbackName) {
5727
+ const fields = extractAndParseFrontmatter(raw, fallbackName);
5728
+ const name = resolveName(fields, fallbackName);
5729
+ ensureRequiredFields(fields, name);
5730
+ return buildFrontmatter(fields, name);
5731
+ }
5732
+ function stripSkillFrontmatter(raw) {
5733
+ const match = /^---\s*\n[\s\S]*?\n---\s*\n/.exec(raw);
5734
+ return (match === null ? raw : raw.slice(match[0].length)).trim();
5735
+ }
5736
+ function extractAndParseFrontmatter(raw, fallbackName) {
5737
+ const match = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(raw);
5738
+ if (match === null) {
5739
+ throw new ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {
5740
+ code: "missing_frontmatter"
5741
+ });
5742
+ }
5743
+ const frontmatter = match[1] ?? "";
5744
+ try {
5745
+ return toStringFields(parseSimpleYaml(frontmatter));
5746
+ } catch (cause) {
5747
+ const detail = cause instanceof Error ? cause.message : String(cause);
5748
+ throw new ConfigurationError(
5749
+ `Skill ${fallbackName} has malformed YAML frontmatter: ${detail}`,
5750
+ { code: "schema_invalid", cause }
5751
+ );
5752
+ }
5753
+ }
5754
+ function resolveName(fields, fallbackName) {
5755
+ if (hasContent(fields.name)) return fields.name;
5756
+ if (hasContent(fallbackName)) return fallbackName;
5757
+ throw new ConfigurationError("Skill at unknown path is missing required field: name", {
5758
+ code: "schema_invalid"
5759
+ });
5760
+ }
5761
+ function ensureRequiredFields(fields, name) {
5762
+ if (!hasContent(fields.description)) {
5763
+ throw new ConfigurationError(`Skill ${name} is missing required field: description`, {
5764
+ code: "schema_invalid"
5765
+ });
5766
+ }
5767
+ }
5768
+ function buildFrontmatter(fields, name) {
5769
+ const description = fields.description;
5770
+ if (description === void 0) {
5771
+ throw new ConfigurationError(`Skill ${name} missing description`, { code: "schema_invalid" });
5772
+ }
5773
+ const result = { name, description };
5774
+ if (hasContent(fields.category)) result.category = fields.category;
5775
+ const deps = parseDependencies(fields.dependencies);
5776
+ if (deps !== void 0) result.dependencies = deps;
5777
+ return result;
5778
+ }
5779
+ function parseDependencies(raw) {
5780
+ if (!hasContent(raw)) return void 0;
5781
+ const deps = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
5782
+ return deps.length > 0 ? deps : void 0;
5783
+ }
5784
+ function hasContent(value) {
5785
+ return value !== void 0 && value.trim().length > 0;
5786
+ }
5787
+ var init_skill_frontmatter = __esm({
5788
+ "src/internal/runtime/skills/skill-frontmatter.ts"() {
5789
+ init_errors();
5790
+ init_yaml_frontmatter();
5791
+ }
5792
+ });
5793
+ async function discoverSkills(dir, options) {
5794
+ let entries;
5795
+ try {
5796
+ entries = await readWorkspaceDir(dir, "skills_read_error", "skills directory");
5797
+ } catch {
5798
+ return [];
5799
+ }
5800
+ const skills = [];
5801
+ for (const entry of entries) {
5802
+ if (!entry.isDirectory()) continue;
5803
+ let skillDir;
5804
+ try {
5805
+ skillDir = safePathJoin(dir, entry.name);
5806
+ assertNoSymlinkEscape(skillDir, dir);
5807
+ } catch {
5808
+ continue;
5809
+ }
5810
+ const skillPath = path.join(skillDir, "SKILL.md");
5811
+ let raw;
5812
+ try {
5813
+ raw = await promises.readFile(skillPath, "utf8");
5814
+ } catch {
5815
+ continue;
5816
+ }
5817
+ const skill = tryParseSkill(raw, entry.name, skillPath, options);
5818
+ if (skill !== void 0) skills.push(skill);
5819
+ }
5820
+ return skills;
5821
+ }
5822
+ function tryParseSkill(raw, fallbackName, source, options) {
5823
+ try {
5824
+ const frontmatter = parseSkillFrontmatter(raw, fallbackName);
5825
+ const skill = {
5826
+ name: frontmatter.name,
5827
+ description: frontmatter.description,
5828
+ source
5829
+ };
5830
+ if (frontmatter.category !== void 0) skill.category = frontmatter.category;
5831
+ if (frontmatter.dependencies !== void 0) skill.dependencies = frontmatter.dependencies;
5832
+ return skill;
5833
+ } catch (cause) {
5834
+ if (cause instanceof ConfigurationError) {
5835
+ options?.onInvalidSkill?.({
5836
+ name: fallbackName,
5837
+ source,
5838
+ code: cause.code ?? "unknown",
5839
+ message: cause.message
5840
+ });
5841
+ return void 0;
5842
+ }
5843
+ throw cause;
5844
+ }
5845
+ }
5846
+ var init_discover_skills = __esm({
5847
+ "src/internal/runtime/skills/discover-skills.ts"() {
5848
+ init_errors();
5849
+ init_path_guard();
5850
+ init_workspace_dir();
5851
+ init_skill_frontmatter();
5852
+ }
5853
+ });
5854
+ var SkillsManager;
5855
+ var init_skills_manager = __esm({
5856
+ "src/internal/runtime/skills/skills-manager.ts"() {
5857
+ init_discover_skills();
5858
+ init_skill_frontmatter();
5859
+ SkillsManager = class {
5860
+ constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
5861
+ this.cwd = cwd;
5862
+ this.settingSourcesIncludeProject = settingSourcesIncludeProject;
5863
+ this.skillsDir = skillsDir;
5864
+ this.inline = inline;
5865
+ }
5866
+ cwd;
5867
+ settingSourcesIncludeProject;
5868
+ skillsDir;
5869
+ inline;
5870
+ skills = [];
5871
+ async initialize() {
5872
+ if (!this.settingSourcesIncludeProject) {
5873
+ this.skills = this.mergeInline([]);
5874
+ return;
5875
+ }
5876
+ await this.refresh();
5877
+ }
5878
+ async refresh() {
5879
+ const skillsRoot = this.skillsDir ?? path.join(this.cwd, ".theokit", "skills");
5880
+ const discovered = await discoverSkills(skillsRoot, {
5881
+ onInvalidSkill: (info) => {
5882
+ process.stderr.write(
5883
+ `[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
5884
+ `
5885
+ );
5886
+ }
5887
+ });
5888
+ this.skills = this.mergeInline(discovered);
5889
+ }
5890
+ /** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
5891
+ mergeInline(discovered) {
5892
+ if (this.inline === void 0 || this.inline.length === 0) return discovered;
5893
+ const inlineNames = new Set(this.inline.map((s) => s.name));
5894
+ return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
5895
+ }
5896
+ list() {
5897
+ return Promise.resolve(this.skills);
5898
+ }
5899
+ /**
5900
+ * SE20 — resolve a skill by name INCLUDING its body. Inline (`createSkill`)
5901
+ * skills carry `instructions` on the object; filesystem skills read the body
5902
+ * from their `source` SKILL.md (frontmatter stripped). `undefined` when no
5903
+ * enabled skill matches (malformed skills were already excluded at discovery).
5904
+ */
5905
+ async get(name) {
5906
+ const skill = this.skills.find((s) => s.name === name);
5907
+ if (skill === void 0) return void 0;
5908
+ const instructions = typeof skill.instructions === "string" ? skill.instructions : stripSkillFrontmatter(await promises.readFile(skill.source, "utf8"));
5909
+ const references = skill.references;
5910
+ return {
5911
+ name: skill.name,
5912
+ description: skill.description,
5913
+ instructions,
5914
+ ...references !== void 0 ? { references } : {}
5915
+ };
5916
+ }
5917
+ };
5918
+ }
5919
+ });
5920
+
5696
5921
  // src/internal/runtime/system-prompt/local-assembly.ts
5697
- async function buildSystemPromptContext(inputs, userText, memoryFacts) {
5698
- const skills = inputs.skillsManager !== void 0 ? await inputs.skillsManager.list() : [];
5922
+ async function resolveSendSkills(inputs, userText, memoryFacts) {
5923
+ const skills = inputs.options.skills;
5924
+ if (typeof skills !== "function") {
5925
+ return { manager: inputs.skillsManager, autoInject: skills?.autoInject ?? true };
5926
+ }
5927
+ const settings = await skills({
5928
+ agentId: inputs.agentId,
5929
+ cwd: inputs.workspaceCwd,
5930
+ model: inputs.model,
5931
+ userMessage: userText,
5932
+ memory: memoryFacts.map((fact) => ({ text: fact.text }))
5933
+ });
5934
+ const manager = new SkillsManager(
5935
+ inputs.workspaceCwd,
5936
+ settings.enabled,
5937
+ inputs.settingSourcesIncludeProject,
5938
+ settings.skillsDir,
5939
+ settings.inline
5940
+ );
5941
+ await manager.initialize();
5942
+ return { manager, autoInject: settings.autoInject ?? true };
5943
+ }
5944
+ async function buildSystemPromptContext(inputs, userText, memoryFacts, manager = inputs.skillsManager) {
5945
+ const skills = manager !== void 0 ? await manager.list() : [];
5699
5946
  return {
5700
5947
  agentId: inputs.agentId,
5701
5948
  cwd: inputs.workspaceCwd,
@@ -5706,10 +5953,11 @@ async function buildSystemPromptContext(inputs, userText, memoryFacts) {
5706
5953
  };
5707
5954
  }
5708
5955
  async function buildAssemblyContext(inputs, userText, baseSystemPrompt, memoryFacts, activeMemorySummary) {
5709
- const baseCtx = await buildSystemPromptContext(inputs, userText, memoryFacts);
5956
+ const resolved = await resolveSendSkills(inputs, userText, memoryFacts);
5957
+ const baseCtx = await buildSystemPromptContext(inputs, userText, memoryFacts, resolved.manager);
5710
5958
  const assemblyCtx = {
5711
5959
  ...baseCtx,
5712
- skillsAutoInject: inputs.options.skills?.autoInject ?? true,
5960
+ skillsAutoInject: resolved.autoInject,
5713
5961
  memoryAutoInject: inputs.options.memory?.autoInject ?? true
5714
5962
  };
5715
5963
  if (baseSystemPrompt !== void 0) assemblyCtx.baseSystemPrompt = baseSystemPrompt;
@@ -5735,6 +5983,7 @@ async function assembleSystemPromptForSend(inputs, userText, baseSystemPrompt, m
5735
5983
  }
5736
5984
  var init_local_assembly = __esm({
5737
5985
  "src/internal/runtime/system-prompt/local-assembly.ts"() {
5986
+ init_skills_manager();
5738
5987
  }
5739
5988
  });
5740
5989
 
@@ -7080,187 +7329,6 @@ var init_plugins_manager = __esm({
7080
7329
  }
7081
7330
  });
7082
7331
 
7083
- // src/internal/runtime/skills/skill-frontmatter.ts
7084
- function asString(v) {
7085
- return typeof v === "string" ? v : void 0;
7086
- }
7087
- function toStringFields(raw) {
7088
- const out = {};
7089
- for (const [k, v] of Object.entries(raw)) out[k] = asString(v);
7090
- return out;
7091
- }
7092
- function parseSkillFrontmatter(raw, fallbackName) {
7093
- const fields = extractAndParseFrontmatter(raw, fallbackName);
7094
- const name = resolveName(fields, fallbackName);
7095
- ensureRequiredFields(fields, name);
7096
- return buildFrontmatter(fields, name);
7097
- }
7098
- function extractAndParseFrontmatter(raw, fallbackName) {
7099
- const match = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(raw);
7100
- if (match === null) {
7101
- throw new ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {
7102
- code: "missing_frontmatter"
7103
- });
7104
- }
7105
- const frontmatter = match[1] ?? "";
7106
- try {
7107
- return toStringFields(parseSimpleYaml(frontmatter));
7108
- } catch (cause) {
7109
- const detail = cause instanceof Error ? cause.message : String(cause);
7110
- throw new ConfigurationError(
7111
- `Skill ${fallbackName} has malformed YAML frontmatter: ${detail}`,
7112
- { code: "schema_invalid", cause }
7113
- );
7114
- }
7115
- }
7116
- function resolveName(fields, fallbackName) {
7117
- if (hasContent(fields.name)) return fields.name;
7118
- if (hasContent(fallbackName)) return fallbackName;
7119
- throw new ConfigurationError("Skill at unknown path is missing required field: name", {
7120
- code: "schema_invalid"
7121
- });
7122
- }
7123
- function ensureRequiredFields(fields, name) {
7124
- if (!hasContent(fields.description)) {
7125
- throw new ConfigurationError(`Skill ${name} is missing required field: description`, {
7126
- code: "schema_invalid"
7127
- });
7128
- }
7129
- }
7130
- function buildFrontmatter(fields, name) {
7131
- const description = fields.description;
7132
- if (description === void 0) {
7133
- throw new ConfigurationError(`Skill ${name} missing description`, { code: "schema_invalid" });
7134
- }
7135
- const result = { name, description };
7136
- if (hasContent(fields.category)) result.category = fields.category;
7137
- const deps = parseDependencies(fields.dependencies);
7138
- if (deps !== void 0) result.dependencies = deps;
7139
- return result;
7140
- }
7141
- function parseDependencies(raw) {
7142
- if (!hasContent(raw)) return void 0;
7143
- const deps = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
7144
- return deps.length > 0 ? deps : void 0;
7145
- }
7146
- function hasContent(value) {
7147
- return value !== void 0 && value.trim().length > 0;
7148
- }
7149
- var init_skill_frontmatter = __esm({
7150
- "src/internal/runtime/skills/skill-frontmatter.ts"() {
7151
- init_errors();
7152
- init_yaml_frontmatter();
7153
- }
7154
- });
7155
- async function discoverSkills(dir, options) {
7156
- let entries;
7157
- try {
7158
- entries = await readWorkspaceDir(dir, "skills_read_error", "skills directory");
7159
- } catch {
7160
- return [];
7161
- }
7162
- const skills = [];
7163
- for (const entry of entries) {
7164
- if (!entry.isDirectory()) continue;
7165
- let skillDir;
7166
- try {
7167
- skillDir = safePathJoin(dir, entry.name);
7168
- assertNoSymlinkEscape(skillDir, dir);
7169
- } catch {
7170
- continue;
7171
- }
7172
- const skillPath = path.join(skillDir, "SKILL.md");
7173
- let raw;
7174
- try {
7175
- raw = await promises.readFile(skillPath, "utf8");
7176
- } catch {
7177
- continue;
7178
- }
7179
- const skill = tryParseSkill(raw, entry.name, skillPath, options);
7180
- if (skill !== void 0) skills.push(skill);
7181
- }
7182
- return skills;
7183
- }
7184
- function tryParseSkill(raw, fallbackName, source, options) {
7185
- try {
7186
- const frontmatter = parseSkillFrontmatter(raw, fallbackName);
7187
- const skill = {
7188
- name: frontmatter.name,
7189
- description: frontmatter.description,
7190
- source
7191
- };
7192
- if (frontmatter.category !== void 0) skill.category = frontmatter.category;
7193
- if (frontmatter.dependencies !== void 0) skill.dependencies = frontmatter.dependencies;
7194
- return skill;
7195
- } catch (cause) {
7196
- if (cause instanceof ConfigurationError) {
7197
- options?.onInvalidSkill?.({
7198
- name: fallbackName,
7199
- source,
7200
- code: cause.code ?? "unknown",
7201
- message: cause.message
7202
- });
7203
- return void 0;
7204
- }
7205
- throw cause;
7206
- }
7207
- }
7208
- var init_discover_skills = __esm({
7209
- "src/internal/runtime/skills/discover-skills.ts"() {
7210
- init_errors();
7211
- init_path_guard();
7212
- init_workspace_dir();
7213
- init_skill_frontmatter();
7214
- }
7215
- });
7216
- var SkillsManager;
7217
- var init_skills_manager = __esm({
7218
- "src/internal/runtime/skills/skills-manager.ts"() {
7219
- init_discover_skills();
7220
- SkillsManager = class {
7221
- constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
7222
- this.cwd = cwd;
7223
- this.settingSourcesIncludeProject = settingSourcesIncludeProject;
7224
- this.skillsDir = skillsDir;
7225
- this.inline = inline;
7226
- }
7227
- cwd;
7228
- settingSourcesIncludeProject;
7229
- skillsDir;
7230
- inline;
7231
- skills = [];
7232
- async initialize() {
7233
- if (!this.settingSourcesIncludeProject) {
7234
- this.skills = this.mergeInline([]);
7235
- return;
7236
- }
7237
- await this.refresh();
7238
- }
7239
- async refresh() {
7240
- const skillsRoot = this.skillsDir ?? path.join(this.cwd, ".theokit", "skills");
7241
- const discovered = await discoverSkills(skillsRoot, {
7242
- onInvalidSkill: (info) => {
7243
- process.stderr.write(
7244
- `[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
7245
- `
7246
- );
7247
- }
7248
- });
7249
- this.skills = this.mergeInline(discovered);
7250
- }
7251
- /** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
7252
- mergeInline(discovered) {
7253
- if (this.inline === void 0 || this.inline.length === 0) return discovered;
7254
- const inlineNames = new Set(this.inline.map((s) => s.name));
7255
- return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
7256
- }
7257
- list() {
7258
- return Promise.resolve(this.skills);
7259
- }
7260
- };
7261
- }
7262
- });
7263
-
7264
7332
  // src/internal/runtime/local-agent/local-agent-bootstrap.ts
7265
7333
  function registerLocalAgent(args) {
7266
7334
  registerAgent({
@@ -7296,16 +7364,23 @@ function bootstrapSubmanagers(args) {
7296
7364
  );
7297
7365
  }
7298
7366
  if (args.options.skills !== void 0 || args.settingSourcesIncludeProject) {
7367
+ const staticSkills = typeof args.options.skills === "function" ? void 0 : args.options.skills;
7299
7368
  out.skillsManager = new SkillsManager(
7300
7369
  args.workspaceCwd,
7301
- args.options.skills?.enabled,
7370
+ staticSkills?.enabled,
7302
7371
  args.settingSourcesIncludeProject,
7303
7372
  // M22 — custom skills directory + inline (code-defined) skills.
7304
- args.options.skills?.skillsDir,
7305
- args.options.skills?.inline
7373
+ staticSkills?.skillsDir,
7374
+ staticSkills?.inline
7306
7375
  );
7307
7376
  const localSkills = out.skillsManager;
7308
- out.skills = { list: () => localSkills.list() };
7377
+ out.skills = {
7378
+ // Project to the public shape (name + description only). Inline skills carry
7379
+ // their body + references on the object; `list()` must never leak them —
7380
+ // the body is reachable exclusively through `get()`.
7381
+ list: async () => (await localSkills.list()).map((s) => ({ name: s.name, description: s.description })),
7382
+ get: (name) => localSkills.get(name)
7383
+ };
7309
7384
  }
7310
7385
  if (args.options.plugins !== void 0 || args.settingSourcesIncludePlugins) {
7311
7386
  out.pluginsManager = new PluginsManager(
@@ -16291,6 +16366,162 @@ var init_abort_utils = __esm({
16291
16366
  }
16292
16367
  });
16293
16368
 
16369
+ // src/internal/runtime/processors/run-processors.ts
16370
+ function fireViolation(processor, violation) {
16371
+ try {
16372
+ processor.onViolation?.(violation);
16373
+ } catch {
16374
+ }
16375
+ }
16376
+ function controlsFor(processor) {
16377
+ return {
16378
+ abort(reason) {
16379
+ throw new ProcessorAbort(processor.id, reason);
16380
+ },
16381
+ warn(message, detail) {
16382
+ fireViolation(processor, {
16383
+ processorId: processor.id,
16384
+ message,
16385
+ ...detail !== void 0 ? { detail } : {}
16386
+ });
16387
+ }
16388
+ };
16389
+ }
16390
+ function selectHandler(processor, phase) {
16391
+ if (phase === "input") {
16392
+ return processor.processInput ? { kind: "input", fn: processor.processInput } : void 0;
16393
+ }
16394
+ return processor.processOutput ? { kind: "output", fn: processor.processOutput } : void 0;
16395
+ }
16396
+ function invokeHandler(handler, value, agentId, controls) {
16397
+ return handler.kind === "input" ? handler.fn({ message: value, agentId, ...controls }) : handler.fn({ text: value, agentId, ...controls });
16398
+ }
16399
+ async function runOneProcessor(processor, value, agentId, phase) {
16400
+ const handler = selectHandler(processor, phase);
16401
+ if (handler === void 0) return { value };
16402
+ try {
16403
+ const out = await invokeHandler(handler, value, agentId, controlsFor(processor));
16404
+ return { value: typeof out === "string" ? out : value };
16405
+ } catch (err) {
16406
+ if (!(err instanceof ProcessorAbort)) throw err;
16407
+ fireViolation(processor, { processorId: err.processorId, message: err.reason });
16408
+ return { tripwire: { reason: err.reason, processorId: err.processorId } };
16409
+ }
16410
+ }
16411
+ async function runPipeline(processors, initial, agentId, phase) {
16412
+ let value = initial;
16413
+ for (const processor of processors) {
16414
+ const step = await runOneProcessor(processor, value, agentId, phase);
16415
+ if ("tripwire" in step) return { kind: "tripwire", tripwire: step.tripwire };
16416
+ value = step.value;
16417
+ }
16418
+ return { kind: "ok", value };
16419
+ }
16420
+ function runInputProcessors(processors, message, agentId) {
16421
+ return runPipeline(processors, message, agentId, "input");
16422
+ }
16423
+ function runOutputProcessors(processors, text, agentId) {
16424
+ return runPipeline(processors, text, agentId, "output");
16425
+ }
16426
+ var ProcessorAbort;
16427
+ var init_run_processors = __esm({
16428
+ "src/internal/runtime/processors/run-processors.ts"() {
16429
+ ProcessorAbort = class {
16430
+ constructor(processorId, reason) {
16431
+ this.processorId = processorId;
16432
+ this.reason = reason;
16433
+ }
16434
+ processorId;
16435
+ reason;
16436
+ };
16437
+ }
16438
+ });
16439
+
16440
+ // src/internal/runtime/processors/tripwire-run.ts
16441
+ function emptyStream() {
16442
+ return {
16443
+ next: () => Promise.resolve({ done: true, value: void 0 }),
16444
+ return: () => Promise.resolve({ done: true, value: void 0 }),
16445
+ throw: (err) => Promise.reject(err),
16446
+ [Symbol.asyncIterator]() {
16447
+ return this;
16448
+ }
16449
+ };
16450
+ }
16451
+ function createTripwireRun(args) {
16452
+ const id = globalThis.crypto.randomUUID();
16453
+ const result = {
16454
+ id,
16455
+ status: "cancelled",
16456
+ tripwire: args.tripwire,
16457
+ ...args.model !== void 0 ? { model: args.model } : {}
16458
+ };
16459
+ const run = {
16460
+ id,
16461
+ agentId: args.agentId,
16462
+ status: "cancelled",
16463
+ ...args.model !== void 0 ? { model: args.model } : {},
16464
+ stream: () => emptyStream(),
16465
+ wait: () => Promise.resolve(result),
16466
+ cancel: () => Promise.resolve(),
16467
+ conversation: () => Promise.resolve([]),
16468
+ supports: (op) => SUPPORTED.has(op),
16469
+ unsupportedReason: (op) => SUPPORTED.has(op) ? void 0 : `operation "${op}" is not available on a tripwire run`,
16470
+ onDidChangeStatus: () => () => {
16471
+ }
16472
+ // already terminal — status never changes
16473
+ };
16474
+ registerRun(run);
16475
+ return run;
16476
+ }
16477
+ var SUPPORTED;
16478
+ var init_tripwire_run = __esm({
16479
+ "src/internal/runtime/processors/tripwire-run.ts"() {
16480
+ init_run_registry();
16481
+ SUPPORTED = /* @__PURE__ */ new Set([
16482
+ "stream",
16483
+ "wait",
16484
+ "cancel",
16485
+ "conversation"
16486
+ ]);
16487
+ }
16488
+ });
16489
+
16490
+ // src/internal/runtime/processors/wrap-output-run.ts
16491
+ function wrapRunWithOutputProcessors(args) {
16492
+ if (args.processors.length === 0) return args.run;
16493
+ const compute = async () => {
16494
+ const result = await args.run.wait();
16495
+ if (result.status !== "finished" || result.result === void 0) return result;
16496
+ const res = await runOutputProcessors(args.processors, result.result, args.agentId);
16497
+ if (res.kind === "ok") return { ...result, result: res.value };
16498
+ emitRunEvent(args.onRunEvent, {
16499
+ type: "tripwire",
16500
+ reason: res.tripwire.reason,
16501
+ processorId: res.tripwire.processorId
16502
+ });
16503
+ const { result: _suppressed, ...metadata } = result;
16504
+ return { ...metadata, status: "cancelled", tripwire: res.tripwire };
16505
+ };
16506
+ let processed;
16507
+ const wrappedWait = () => {
16508
+ processed ??= compute();
16509
+ return processed;
16510
+ };
16511
+ return new Proxy(args.run, {
16512
+ get(target, prop, receiver) {
16513
+ if (prop === "wait") return wrappedWait;
16514
+ return Reflect.get(target, prop, receiver);
16515
+ }
16516
+ });
16517
+ }
16518
+ var init_wrap_output_run = __esm({
16519
+ "src/internal/runtime/processors/wrap-output-run.ts"() {
16520
+ init_run_events();
16521
+ init_run_processors();
16522
+ }
16523
+ });
16524
+
16294
16525
  // src/internal/runtime/local-agent/local-agent-memory-hooks.ts
16295
16526
  async function applyPreUserSendHook(args) {
16296
16527
  const handlers = args.pluginManager.hooksFor("pre_user_send");
@@ -16343,11 +16574,38 @@ var init_local_agent_memory_hooks = __esm({
16343
16574
  });
16344
16575
 
16345
16576
  // src/internal/runtime/local-agent/local-agent-send.ts
16577
+ async function applyInputProcessors(inputs, message, rawUserText, options, sendModel) {
16578
+ const processors = inputs.options.inputProcessors;
16579
+ if (processors === void 0 || processors.length === 0) {
16580
+ return { userText: rawUserText, effectiveMessage: message };
16581
+ }
16582
+ const res = await runInputProcessors(processors, rawUserText, inputs.agentId);
16583
+ if (res.kind === "tripwire") {
16584
+ emitRunEvent(options.onRunEvent, {
16585
+ type: "tripwire",
16586
+ reason: res.tripwire.reason,
16587
+ processorId: res.tripwire.processorId
16588
+ });
16589
+ return {
16590
+ tripwireRun: createTripwireRun({
16591
+ agentId: inputs.agentId,
16592
+ tripwire: res.tripwire,
16593
+ model: sendModel
16594
+ })
16595
+ };
16596
+ }
16597
+ const effectiveMessage = typeof message === "string" ? res.value : { ...message, text: res.value };
16598
+ return { userText: res.value, effectiveMessage };
16599
+ }
16346
16600
  async function executeSendLocked(inputs, message, options) {
16347
16601
  if (inputs.disposed) throw new AgentDisposedError(inputs.agentId);
16348
16602
  await consumePending(inputs.agentId, inputs.invalidationPending, inputs.clearInvalidation, inputs.reload);
16349
- inputs.applyModelOverride(normalizeModel(options.model));
16350
- const userText = typeof message === "string" ? message : message.text;
16603
+ const sendModel = normalizeModel(options.model);
16604
+ inputs.applyModelOverride(sendModel);
16605
+ const rawUserText = typeof message === "string" ? message : message.text;
16606
+ const gated = await applyInputProcessors(inputs, message, rawUserText, options, sendModel);
16607
+ if ("tripwireRun" in gated) return gated.tripwireRun;
16608
+ const { userText, effectiveMessage } = gated;
16351
16609
  if (inputs.options.onBeforeSend !== void 0) {
16352
16610
  await inputs.options.onBeforeSend({
16353
16611
  conversationId: inputs.agentId,
@@ -16359,7 +16617,7 @@ async function executeSendLocked(inputs, message, options) {
16359
16617
  pluginManager: inputs.pluginManagerCode,
16360
16618
  agentId: inputs.agentId,
16361
16619
  options: inputs.options,
16362
- original: message,
16620
+ original: effectiveMessage,
16363
16621
  userText,
16364
16622
  sendOptions: options
16365
16623
  });
@@ -16397,11 +16655,18 @@ async function executeSendLocked(inputs, message, options) {
16397
16655
  memoryTools,
16398
16656
  effectiveMemoryProvider
16399
16657
  );
16658
+ const outputProcessors = inputs.options.outputProcessors;
16659
+ const processedRun = outputProcessors !== void 0 && outputProcessors.length > 0 ? wrapRunWithOutputProcessors({
16660
+ run,
16661
+ processors: outputProcessors,
16662
+ agentId: inputs.agentId,
16663
+ onRunEvent: options.onRunEvent
16664
+ }) : run;
16400
16665
  return wrapRunWithPostReplyHook({
16401
16666
  pluginManager: inputs.pluginManagerCode,
16402
16667
  agentId: inputs.agentId,
16403
16668
  options: inputs.options,
16404
- run,
16669
+ run: processedRun,
16405
16670
  userText
16406
16671
  });
16407
16672
  }
@@ -16412,10 +16677,14 @@ function readMemoryForSend(workspaceCwd, memoryConfig) {
16412
16677
  var init_local_agent_send = __esm({
16413
16678
  "src/internal/runtime/local-agent/local-agent-send.ts"() {
16414
16679
  init_errors();
16680
+ init_run_events();
16415
16681
  init_abort_utils();
16416
16682
  init_memory_path_selector();
16417
16683
  init_memory_store();
16418
16684
  init_model_selection();
16685
+ init_run_processors();
16686
+ init_tripwire_run();
16687
+ init_wrap_output_run();
16419
16688
  init_agent_session();
16420
16689
  init_safe_call();
16421
16690
  init_local_agent_invalidate();
@@ -17235,7 +17504,7 @@ var init_local_agent = __esm({
17235
17504
  }
17236
17505
  // biome-ignore format: G8 budget — thin accessor for the assembly inputs.
17237
17506
  assemblyInputs() {
17238
- return { agentId: this.agentId, workspaceCwd: this.workspaceCwd, model: this.model, options: this.options, context: this.context, skillsManager: this.skillsManager, systemPromptPipeline: this.systemPromptPipeline };
17507
+ 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 };
17239
17508
  }
17240
17509
  async resolveSystemPrompt(userText, options, memoryFacts) {
17241
17510
  const base = await resolveSystemPromptForSend(