@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/index.js CHANGED
@@ -572,10 +572,10 @@ function buildToolPrompt(prompt) {
572
572
  Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
573
573
  }
574
574
  function setupStructuredOutput(schema, maxRetries) {
575
- const z8 = requireZod();
575
+ const z9 = requireZod();
576
576
  const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
577
577
  return {
578
- z: z8,
578
+ z: z9,
579
579
  jsonSchema,
580
580
  maxRetries: maxRetries ?? 1,
581
581
  initialUsage: { inputTokens: 0, outputTokens: 0 }
@@ -6043,7 +6043,8 @@ function stripSecretsFromOptions(options) {
6043
6043
  local: serializeLocal(options.local),
6044
6044
  cloud: serializeCloud(options.cloud),
6045
6045
  memory: serializeMemory(options.memory),
6046
- skills: serializeEnabledList(options.skills),
6046
+ // SE22 — a SkillsResolver function isn't serializable; persist only the static form.
6047
+ skills: serializeEnabledList(typeof options.skills === "function" ? void 0 : options.skills),
6047
6048
  // Code-`Plugin` objects are closures and cannot be persisted (like custom
6048
6049
  // tools); only the named-enable settings form is serialized.
6049
6050
  plugins: serializeEnabledList(asPluginsSettings(options.plugins)),
@@ -6351,6 +6352,7 @@ function serializeCloud2(cloud) {
6351
6352
  return result;
6352
6353
  }
6353
6354
  function serializeSkills(skills) {
6355
+ if (typeof skills === "function") return void 0;
6354
6356
  if (skills?.enabled === void 0 || skills.enabled.length === 0) return void 0;
6355
6357
  return { enabled: [...skills.enabled] };
6356
6358
  }
@@ -7731,8 +7733,19 @@ init_errors();
7731
7733
  function validateCloudToolParity(options) {
7732
7734
  if (options.cloud === void 0) return;
7733
7735
  rejectFunctionSystemPrompt(options);
7736
+ rejectFunctionSkills(options);
7737
+ rejectProcessors(options);
7734
7738
  rejectStdioMcpLocalPaths(options);
7735
7739
  }
7740
+ function rejectProcessors(options) {
7741
+ const hasProcessors = (options.inputProcessors?.length ?? 0) > 0 || (options.outputProcessors?.length ?? 0) > 0;
7742
+ if (hasProcessors) {
7743
+ throw new ConfigurationError(
7744
+ "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.",
7745
+ { code: "cloud_incompatible_function_resolver" }
7746
+ );
7747
+ }
7748
+ }
7736
7749
  function rejectFunctionSystemPrompt(options) {
7737
7750
  if (typeof options.systemPrompt === "function") {
7738
7751
  throw new ConfigurationError(
@@ -7741,6 +7754,14 @@ function rejectFunctionSystemPrompt(options) {
7741
7754
  );
7742
7755
  }
7743
7756
  }
7757
+ function rejectFunctionSkills(options) {
7758
+ if (typeof options.skills === "function") {
7759
+ throw new ConfigurationError(
7760
+ "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.",
7761
+ { code: "cloud_incompatible_function_resolver" }
7762
+ );
7763
+ }
7764
+ }
7744
7765
  function rejectStdioMcpLocalPaths(options) {
7745
7766
  if (options.mcpServers === void 0) return;
7746
7767
  for (const [name, config] of Object.entries(options.mcpServers)) {
@@ -9567,9 +9588,224 @@ function parseFrontmatterFields(frontmatter) {
9567
9588
  return out;
9568
9589
  }
9569
9590
 
9591
+ // src/internal/runtime/skills/discover-skills.ts
9592
+ init_errors();
9593
+ init_path_guard();
9594
+
9595
+ // src/internal/runtime/skills/skill-frontmatter.ts
9596
+ init_errors();
9597
+ init_yaml_frontmatter();
9598
+ function asString(v) {
9599
+ return typeof v === "string" ? v : void 0;
9600
+ }
9601
+ function toStringFields(raw) {
9602
+ const out = {};
9603
+ for (const [k, v] of Object.entries(raw)) out[k] = asString(v);
9604
+ return out;
9605
+ }
9606
+ function parseSkillFrontmatter(raw, fallbackName) {
9607
+ const fields = extractAndParseFrontmatter(raw, fallbackName);
9608
+ const name = resolveName(fields, fallbackName);
9609
+ ensureRequiredFields(fields, name);
9610
+ return buildFrontmatter(fields, name);
9611
+ }
9612
+ function stripSkillFrontmatter(raw) {
9613
+ const match = /^---\s*\n[\s\S]*?\n---\s*\n/.exec(raw);
9614
+ return (match === null ? raw : raw.slice(match[0].length)).trim();
9615
+ }
9616
+ function extractAndParseFrontmatter(raw, fallbackName) {
9617
+ const match = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(raw);
9618
+ if (match === null) {
9619
+ throw new ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {
9620
+ code: "missing_frontmatter"
9621
+ });
9622
+ }
9623
+ const frontmatter = match[1] ?? "";
9624
+ try {
9625
+ return toStringFields(parseSimpleYaml(frontmatter));
9626
+ } catch (cause) {
9627
+ const detail = cause instanceof Error ? cause.message : String(cause);
9628
+ throw new ConfigurationError(
9629
+ `Skill ${fallbackName} has malformed YAML frontmatter: ${detail}`,
9630
+ { code: "schema_invalid", cause }
9631
+ );
9632
+ }
9633
+ }
9634
+ function resolveName(fields, fallbackName) {
9635
+ if (hasContent(fields.name)) return fields.name;
9636
+ if (hasContent(fallbackName)) return fallbackName;
9637
+ throw new ConfigurationError("Skill at unknown path is missing required field: name", {
9638
+ code: "schema_invalid"
9639
+ });
9640
+ }
9641
+ function ensureRequiredFields(fields, name) {
9642
+ if (!hasContent(fields.description)) {
9643
+ throw new ConfigurationError(`Skill ${name} is missing required field: description`, {
9644
+ code: "schema_invalid"
9645
+ });
9646
+ }
9647
+ }
9648
+ function buildFrontmatter(fields, name) {
9649
+ const description = fields.description;
9650
+ if (description === void 0) {
9651
+ throw new ConfigurationError(`Skill ${name} missing description`, { code: "schema_invalid" });
9652
+ }
9653
+ const result = { name, description };
9654
+ if (hasContent(fields.category)) result.category = fields.category;
9655
+ const deps = parseDependencies(fields.dependencies);
9656
+ if (deps !== void 0) result.dependencies = deps;
9657
+ return result;
9658
+ }
9659
+ function parseDependencies(raw) {
9660
+ if (!hasContent(raw)) return void 0;
9661
+ const deps = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
9662
+ return deps.length > 0 ? deps : void 0;
9663
+ }
9664
+ function hasContent(value) {
9665
+ return value !== void 0 && value.trim().length > 0;
9666
+ }
9667
+
9668
+ // src/internal/runtime/skills/discover-skills.ts
9669
+ async function discoverSkills(dir, options) {
9670
+ let entries;
9671
+ try {
9672
+ entries = await readWorkspaceDir(dir, "skills_read_error", "skills directory");
9673
+ } catch {
9674
+ return [];
9675
+ }
9676
+ const skills = [];
9677
+ for (const entry of entries) {
9678
+ if (!entry.isDirectory()) continue;
9679
+ let skillDir;
9680
+ try {
9681
+ skillDir = safePathJoin(dir, entry.name);
9682
+ assertNoSymlinkEscape(skillDir, dir);
9683
+ } catch {
9684
+ continue;
9685
+ }
9686
+ const skillPath = join(skillDir, "SKILL.md");
9687
+ let raw;
9688
+ try {
9689
+ raw = await readFile(skillPath, "utf8");
9690
+ } catch {
9691
+ continue;
9692
+ }
9693
+ const skill = tryParseSkill(raw, entry.name, skillPath, options);
9694
+ if (skill !== void 0) skills.push(skill);
9695
+ }
9696
+ return skills;
9697
+ }
9698
+ function tryParseSkill(raw, fallbackName, source, options) {
9699
+ try {
9700
+ const frontmatter = parseSkillFrontmatter(raw, fallbackName);
9701
+ const skill = {
9702
+ name: frontmatter.name,
9703
+ description: frontmatter.description,
9704
+ source
9705
+ };
9706
+ if (frontmatter.category !== void 0) skill.category = frontmatter.category;
9707
+ if (frontmatter.dependencies !== void 0) skill.dependencies = frontmatter.dependencies;
9708
+ return skill;
9709
+ } catch (cause) {
9710
+ if (cause instanceof ConfigurationError) {
9711
+ options?.onInvalidSkill?.({
9712
+ name: fallbackName,
9713
+ source,
9714
+ code: cause.code ?? "unknown",
9715
+ message: cause.message
9716
+ });
9717
+ return void 0;
9718
+ }
9719
+ throw cause;
9720
+ }
9721
+ }
9722
+
9723
+ // src/internal/runtime/skills/skills-manager.ts
9724
+ var SkillsManager = class {
9725
+ constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
9726
+ this.cwd = cwd;
9727
+ this.settingSourcesIncludeProject = settingSourcesIncludeProject;
9728
+ this.skillsDir = skillsDir;
9729
+ this.inline = inline;
9730
+ }
9731
+ cwd;
9732
+ settingSourcesIncludeProject;
9733
+ skillsDir;
9734
+ inline;
9735
+ skills = [];
9736
+ async initialize() {
9737
+ if (!this.settingSourcesIncludeProject) {
9738
+ this.skills = this.mergeInline([]);
9739
+ return;
9740
+ }
9741
+ await this.refresh();
9742
+ }
9743
+ async refresh() {
9744
+ const skillsRoot = this.skillsDir ?? join(this.cwd, ".theokit", "skills");
9745
+ const discovered = await discoverSkills(skillsRoot, {
9746
+ onInvalidSkill: (info) => {
9747
+ process.stderr.write(
9748
+ `[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
9749
+ `
9750
+ );
9751
+ }
9752
+ });
9753
+ this.skills = this.mergeInline(discovered);
9754
+ }
9755
+ /** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
9756
+ mergeInline(discovered) {
9757
+ if (this.inline === void 0 || this.inline.length === 0) return discovered;
9758
+ const inlineNames = new Set(this.inline.map((s) => s.name));
9759
+ return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
9760
+ }
9761
+ list() {
9762
+ return Promise.resolve(this.skills);
9763
+ }
9764
+ /**
9765
+ * SE20 — resolve a skill by name INCLUDING its body. Inline (`createSkill`)
9766
+ * skills carry `instructions` on the object; filesystem skills read the body
9767
+ * from their `source` SKILL.md (frontmatter stripped). `undefined` when no
9768
+ * enabled skill matches (malformed skills were already excluded at discovery).
9769
+ */
9770
+ async get(name) {
9771
+ const skill = this.skills.find((s) => s.name === name);
9772
+ if (skill === void 0) return void 0;
9773
+ const instructions = typeof skill.instructions === "string" ? skill.instructions : stripSkillFrontmatter(await readFile(skill.source, "utf8"));
9774
+ const references = skill.references;
9775
+ return {
9776
+ name: skill.name,
9777
+ description: skill.description,
9778
+ instructions,
9779
+ ...references !== void 0 ? { references } : {}
9780
+ };
9781
+ }
9782
+ };
9783
+
9570
9784
  // src/internal/runtime/system-prompt/local-assembly.ts
9571
- async function buildSystemPromptContext(inputs, userText, memoryFacts) {
9572
- const skills = inputs.skillsManager !== void 0 ? await inputs.skillsManager.list() : [];
9785
+ async function resolveSendSkills(inputs, userText, memoryFacts) {
9786
+ const skills = inputs.options.skills;
9787
+ if (typeof skills !== "function") {
9788
+ return { manager: inputs.skillsManager, autoInject: skills?.autoInject ?? true };
9789
+ }
9790
+ const settings = await skills({
9791
+ agentId: inputs.agentId,
9792
+ cwd: inputs.workspaceCwd,
9793
+ model: inputs.model,
9794
+ userMessage: userText,
9795
+ memory: memoryFacts.map((fact) => ({ text: fact.text }))
9796
+ });
9797
+ const manager = new SkillsManager(
9798
+ inputs.workspaceCwd,
9799
+ settings.enabled,
9800
+ inputs.settingSourcesIncludeProject,
9801
+ settings.skillsDir,
9802
+ settings.inline
9803
+ );
9804
+ await manager.initialize();
9805
+ return { manager, autoInject: settings.autoInject ?? true };
9806
+ }
9807
+ async function buildSystemPromptContext(inputs, userText, memoryFacts, manager = inputs.skillsManager) {
9808
+ const skills = manager !== void 0 ? await manager.list() : [];
9573
9809
  return {
9574
9810
  agentId: inputs.agentId,
9575
9811
  cwd: inputs.workspaceCwd,
@@ -9580,10 +9816,11 @@ async function buildSystemPromptContext(inputs, userText, memoryFacts) {
9580
9816
  };
9581
9817
  }
9582
9818
  async function buildAssemblyContext(inputs, userText, baseSystemPrompt, memoryFacts, activeMemorySummary) {
9583
- const baseCtx = await buildSystemPromptContext(inputs, userText, memoryFacts);
9819
+ const resolved = await resolveSendSkills(inputs, userText, memoryFacts);
9820
+ const baseCtx = await buildSystemPromptContext(inputs, userText, memoryFacts, resolved.manager);
9584
9821
  const assemblyCtx = {
9585
9822
  ...baseCtx,
9586
- skillsAutoInject: inputs.options.skills?.autoInject ?? true,
9823
+ skillsAutoInject: resolved.autoInject,
9587
9824
  memoryAutoInject: inputs.options.memory?.autoInject ?? true
9588
9825
  };
9589
9826
  if (baseSystemPrompt !== void 0) assemblyCtx.baseSystemPrompt = baseSystemPrompt;
@@ -10836,177 +11073,6 @@ async function loadPluginManifestFromMarkdown(pluginsRoot, folderName) {
10836
11073
  return metadata;
10837
11074
  }
10838
11075
 
10839
- // src/internal/runtime/skills/discover-skills.ts
10840
- init_errors();
10841
- init_path_guard();
10842
-
10843
- // src/internal/runtime/skills/skill-frontmatter.ts
10844
- init_errors();
10845
- init_yaml_frontmatter();
10846
- function asString(v) {
10847
- return typeof v === "string" ? v : void 0;
10848
- }
10849
- function toStringFields(raw) {
10850
- const out = {};
10851
- for (const [k, v] of Object.entries(raw)) out[k] = asString(v);
10852
- return out;
10853
- }
10854
- function parseSkillFrontmatter(raw, fallbackName) {
10855
- const fields = extractAndParseFrontmatter(raw, fallbackName);
10856
- const name = resolveName(fields, fallbackName);
10857
- ensureRequiredFields(fields, name);
10858
- return buildFrontmatter(fields, name);
10859
- }
10860
- function extractAndParseFrontmatter(raw, fallbackName) {
10861
- const match = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(raw);
10862
- if (match === null) {
10863
- throw new ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {
10864
- code: "missing_frontmatter"
10865
- });
10866
- }
10867
- const frontmatter = match[1] ?? "";
10868
- try {
10869
- return toStringFields(parseSimpleYaml(frontmatter));
10870
- } catch (cause) {
10871
- const detail = cause instanceof Error ? cause.message : String(cause);
10872
- throw new ConfigurationError(
10873
- `Skill ${fallbackName} has malformed YAML frontmatter: ${detail}`,
10874
- { code: "schema_invalid", cause }
10875
- );
10876
- }
10877
- }
10878
- function resolveName(fields, fallbackName) {
10879
- if (hasContent(fields.name)) return fields.name;
10880
- if (hasContent(fallbackName)) return fallbackName;
10881
- throw new ConfigurationError("Skill at unknown path is missing required field: name", {
10882
- code: "schema_invalid"
10883
- });
10884
- }
10885
- function ensureRequiredFields(fields, name) {
10886
- if (!hasContent(fields.description)) {
10887
- throw new ConfigurationError(`Skill ${name} is missing required field: description`, {
10888
- code: "schema_invalid"
10889
- });
10890
- }
10891
- }
10892
- function buildFrontmatter(fields, name) {
10893
- const description = fields.description;
10894
- if (description === void 0) {
10895
- throw new ConfigurationError(`Skill ${name} missing description`, { code: "schema_invalid" });
10896
- }
10897
- const result = { name, description };
10898
- if (hasContent(fields.category)) result.category = fields.category;
10899
- const deps = parseDependencies(fields.dependencies);
10900
- if (deps !== void 0) result.dependencies = deps;
10901
- return result;
10902
- }
10903
- function parseDependencies(raw) {
10904
- if (!hasContent(raw)) return void 0;
10905
- const deps = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
10906
- return deps.length > 0 ? deps : void 0;
10907
- }
10908
- function hasContent(value) {
10909
- return value !== void 0 && value.trim().length > 0;
10910
- }
10911
-
10912
- // src/internal/runtime/skills/discover-skills.ts
10913
- async function discoverSkills(dir, options) {
10914
- let entries;
10915
- try {
10916
- entries = await readWorkspaceDir(dir, "skills_read_error", "skills directory");
10917
- } catch {
10918
- return [];
10919
- }
10920
- const skills = [];
10921
- for (const entry of entries) {
10922
- if (!entry.isDirectory()) continue;
10923
- let skillDir;
10924
- try {
10925
- skillDir = safePathJoin(dir, entry.name);
10926
- assertNoSymlinkEscape(skillDir, dir);
10927
- } catch {
10928
- continue;
10929
- }
10930
- const skillPath = join(skillDir, "SKILL.md");
10931
- let raw;
10932
- try {
10933
- raw = await readFile(skillPath, "utf8");
10934
- } catch {
10935
- continue;
10936
- }
10937
- const skill = tryParseSkill(raw, entry.name, skillPath, options);
10938
- if (skill !== void 0) skills.push(skill);
10939
- }
10940
- return skills;
10941
- }
10942
- function tryParseSkill(raw, fallbackName, source, options) {
10943
- try {
10944
- const frontmatter = parseSkillFrontmatter(raw, fallbackName);
10945
- const skill = {
10946
- name: frontmatter.name,
10947
- description: frontmatter.description,
10948
- source
10949
- };
10950
- if (frontmatter.category !== void 0) skill.category = frontmatter.category;
10951
- if (frontmatter.dependencies !== void 0) skill.dependencies = frontmatter.dependencies;
10952
- return skill;
10953
- } catch (cause) {
10954
- if (cause instanceof ConfigurationError) {
10955
- options?.onInvalidSkill?.({
10956
- name: fallbackName,
10957
- source,
10958
- code: cause.code ?? "unknown",
10959
- message: cause.message
10960
- });
10961
- return void 0;
10962
- }
10963
- throw cause;
10964
- }
10965
- }
10966
-
10967
- // src/internal/runtime/skills/skills-manager.ts
10968
- var SkillsManager = class {
10969
- constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
10970
- this.cwd = cwd;
10971
- this.settingSourcesIncludeProject = settingSourcesIncludeProject;
10972
- this.skillsDir = skillsDir;
10973
- this.inline = inline;
10974
- }
10975
- cwd;
10976
- settingSourcesIncludeProject;
10977
- skillsDir;
10978
- inline;
10979
- skills = [];
10980
- async initialize() {
10981
- if (!this.settingSourcesIncludeProject) {
10982
- this.skills = this.mergeInline([]);
10983
- return;
10984
- }
10985
- await this.refresh();
10986
- }
10987
- async refresh() {
10988
- const skillsRoot = this.skillsDir ?? join(this.cwd, ".theokit", "skills");
10989
- const discovered = await discoverSkills(skillsRoot, {
10990
- onInvalidSkill: (info) => {
10991
- process.stderr.write(
10992
- `[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
10993
- `
10994
- );
10995
- }
10996
- });
10997
- this.skills = this.mergeInline(discovered);
10998
- }
10999
- /** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
11000
- mergeInline(discovered) {
11001
- if (this.inline === void 0 || this.inline.length === 0) return discovered;
11002
- const inlineNames = new Set(this.inline.map((s) => s.name));
11003
- return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
11004
- }
11005
- list() {
11006
- return Promise.resolve(this.skills);
11007
- }
11008
- };
11009
-
11010
11076
  // src/internal/runtime/local-agent/local-agent-bootstrap.ts
11011
11077
  function registerLocalAgent(args) {
11012
11078
  registerAgent({
@@ -11042,16 +11108,23 @@ function bootstrapSubmanagers(args) {
11042
11108
  );
11043
11109
  }
11044
11110
  if (args.options.skills !== void 0 || args.settingSourcesIncludeProject) {
11111
+ const staticSkills = typeof args.options.skills === "function" ? void 0 : args.options.skills;
11045
11112
  out.skillsManager = new SkillsManager(
11046
11113
  args.workspaceCwd,
11047
- args.options.skills?.enabled,
11114
+ staticSkills?.enabled,
11048
11115
  args.settingSourcesIncludeProject,
11049
11116
  // M22 — custom skills directory + inline (code-defined) skills.
11050
- args.options.skills?.skillsDir,
11051
- args.options.skills?.inline
11117
+ staticSkills?.skillsDir,
11118
+ staticSkills?.inline
11052
11119
  );
11053
11120
  const localSkills = out.skillsManager;
11054
- out.skills = { list: () => localSkills.list() };
11121
+ out.skills = {
11122
+ // Project to the public shape (name + description only). Inline skills carry
11123
+ // their body + references on the object; `list()` must never leak them —
11124
+ // the body is reachable exclusively through `get()`.
11125
+ list: async () => (await localSkills.list()).map((s) => ({ name: s.name, description: s.description })),
11126
+ get: (name) => localSkills.get(name)
11127
+ };
11055
11128
  }
11056
11129
  if (args.options.plugins !== void 0 || args.settingSourcesIncludePlugins) {
11057
11130
  out.pluginsManager = new PluginsManager(
@@ -17611,6 +17684,145 @@ function ponyfillAny(signals) {
17611
17684
  return ctrl.signal;
17612
17685
  }
17613
17686
 
17687
+ // src/internal/runtime/processors/run-processors.ts
17688
+ var ProcessorAbort = class {
17689
+ constructor(processorId, reason) {
17690
+ this.processorId = processorId;
17691
+ this.reason = reason;
17692
+ }
17693
+ processorId;
17694
+ reason;
17695
+ };
17696
+ function fireViolation(processor, violation) {
17697
+ try {
17698
+ processor.onViolation?.(violation);
17699
+ } catch {
17700
+ }
17701
+ }
17702
+ function controlsFor(processor) {
17703
+ return {
17704
+ abort(reason) {
17705
+ throw new ProcessorAbort(processor.id, reason);
17706
+ },
17707
+ warn(message, detail) {
17708
+ fireViolation(processor, {
17709
+ processorId: processor.id,
17710
+ message,
17711
+ ...detail !== void 0 ? { detail } : {}
17712
+ });
17713
+ }
17714
+ };
17715
+ }
17716
+ function selectHandler(processor, phase) {
17717
+ if (phase === "input") {
17718
+ return processor.processInput ? { kind: "input", fn: processor.processInput } : void 0;
17719
+ }
17720
+ return processor.processOutput ? { kind: "output", fn: processor.processOutput } : void 0;
17721
+ }
17722
+ function invokeHandler(handler, value, agentId, controls) {
17723
+ return handler.kind === "input" ? handler.fn({ message: value, agentId, ...controls }) : handler.fn({ text: value, agentId, ...controls });
17724
+ }
17725
+ async function runOneProcessor(processor, value, agentId, phase) {
17726
+ const handler = selectHandler(processor, phase);
17727
+ if (handler === void 0) return { value };
17728
+ try {
17729
+ const out = await invokeHandler(handler, value, agentId, controlsFor(processor));
17730
+ return { value: typeof out === "string" ? out : value };
17731
+ } catch (err) {
17732
+ if (!(err instanceof ProcessorAbort)) throw err;
17733
+ fireViolation(processor, { processorId: err.processorId, message: err.reason });
17734
+ return { tripwire: { reason: err.reason, processorId: err.processorId } };
17735
+ }
17736
+ }
17737
+ async function runPipeline(processors, initial, agentId, phase) {
17738
+ let value = initial;
17739
+ for (const processor of processors) {
17740
+ const step = await runOneProcessor(processor, value, agentId, phase);
17741
+ if ("tripwire" in step) return { kind: "tripwire", tripwire: step.tripwire };
17742
+ value = step.value;
17743
+ }
17744
+ return { kind: "ok", value };
17745
+ }
17746
+ function runInputProcessors(processors, message, agentId) {
17747
+ return runPipeline(processors, message, agentId, "input");
17748
+ }
17749
+ function runOutputProcessors(processors, text, agentId) {
17750
+ return runPipeline(processors, text, agentId, "output");
17751
+ }
17752
+
17753
+ // src/internal/runtime/processors/tripwire-run.ts
17754
+ var SUPPORTED = /* @__PURE__ */ new Set([
17755
+ "stream",
17756
+ "wait",
17757
+ "cancel",
17758
+ "conversation"
17759
+ ]);
17760
+ function emptyStream() {
17761
+ return {
17762
+ next: () => Promise.resolve({ done: true, value: void 0 }),
17763
+ return: () => Promise.resolve({ done: true, value: void 0 }),
17764
+ throw: (err) => Promise.reject(err),
17765
+ [Symbol.asyncIterator]() {
17766
+ return this;
17767
+ }
17768
+ };
17769
+ }
17770
+ function createTripwireRun(args) {
17771
+ const id = globalThis.crypto.randomUUID();
17772
+ const result = {
17773
+ id,
17774
+ status: "cancelled",
17775
+ tripwire: args.tripwire,
17776
+ ...args.model !== void 0 ? { model: args.model } : {}
17777
+ };
17778
+ const run = {
17779
+ id,
17780
+ agentId: args.agentId,
17781
+ status: "cancelled",
17782
+ ...args.model !== void 0 ? { model: args.model } : {},
17783
+ stream: () => emptyStream(),
17784
+ wait: () => Promise.resolve(result),
17785
+ cancel: () => Promise.resolve(),
17786
+ conversation: () => Promise.resolve([]),
17787
+ supports: (op) => SUPPORTED.has(op),
17788
+ unsupportedReason: (op) => SUPPORTED.has(op) ? void 0 : `operation "${op}" is not available on a tripwire run`,
17789
+ onDidChangeStatus: () => () => {
17790
+ }
17791
+ // already terminal — status never changes
17792
+ };
17793
+ registerRun(run);
17794
+ return run;
17795
+ }
17796
+
17797
+ // src/internal/runtime/processors/wrap-output-run.ts
17798
+ function wrapRunWithOutputProcessors(args) {
17799
+ if (args.processors.length === 0) return args.run;
17800
+ const compute = async () => {
17801
+ const result = await args.run.wait();
17802
+ if (result.status !== "finished" || result.result === void 0) return result;
17803
+ const res = await runOutputProcessors(args.processors, result.result, args.agentId);
17804
+ if (res.kind === "ok") return { ...result, result: res.value };
17805
+ emitRunEvent(args.onRunEvent, {
17806
+ type: "tripwire",
17807
+ reason: res.tripwire.reason,
17808
+ processorId: res.tripwire.processorId
17809
+ });
17810
+ const { result: _suppressed, ...metadata } = result;
17811
+ return { ...metadata, status: "cancelled", tripwire: res.tripwire };
17812
+ };
17813
+ let processed;
17814
+ const wrappedWait = () => {
17815
+ processed ??= compute();
17816
+ return processed;
17817
+ };
17818
+ return new Proxy(args.run, {
17819
+ get(target, prop, receiver) {
17820
+ if (prop === "wait") return wrappedWait;
17821
+ return Reflect.get(target, prop, receiver);
17822
+ }
17823
+ });
17824
+ }
17825
+
17614
17826
  // src/internal/runtime/local-agent/local-agent-memory-hooks.ts
17615
17827
  var DEFAULT_MAX_RECALL_BYTES = 16e3;
17616
17828
  async function applyPreUserSendHook(args) {
@@ -17658,11 +17870,38 @@ function wrapRunWithPostReplyHook(args) {
17658
17870
  }
17659
17871
 
17660
17872
  // src/internal/runtime/local-agent/local-agent-send.ts
17873
+ async function applyInputProcessors(inputs, message, rawUserText, options, sendModel) {
17874
+ const processors = inputs.options.inputProcessors;
17875
+ if (processors === void 0 || processors.length === 0) {
17876
+ return { userText: rawUserText, effectiveMessage: message };
17877
+ }
17878
+ const res = await runInputProcessors(processors, rawUserText, inputs.agentId);
17879
+ if (res.kind === "tripwire") {
17880
+ emitRunEvent(options.onRunEvent, {
17881
+ type: "tripwire",
17882
+ reason: res.tripwire.reason,
17883
+ processorId: res.tripwire.processorId
17884
+ });
17885
+ return {
17886
+ tripwireRun: createTripwireRun({
17887
+ agentId: inputs.agentId,
17888
+ tripwire: res.tripwire,
17889
+ model: sendModel
17890
+ })
17891
+ };
17892
+ }
17893
+ const effectiveMessage = typeof message === "string" ? res.value : { ...message, text: res.value };
17894
+ return { userText: res.value, effectiveMessage };
17895
+ }
17661
17896
  async function executeSendLocked(inputs, message, options) {
17662
17897
  if (inputs.disposed) throw new AgentDisposedError(inputs.agentId);
17663
17898
  await consumePending(inputs.agentId, inputs.invalidationPending, inputs.clearInvalidation, inputs.reload);
17664
- inputs.applyModelOverride(normalizeModel(options.model));
17665
- const userText = typeof message === "string" ? message : message.text;
17899
+ const sendModel = normalizeModel(options.model);
17900
+ inputs.applyModelOverride(sendModel);
17901
+ const rawUserText = typeof message === "string" ? message : message.text;
17902
+ const gated = await applyInputProcessors(inputs, message, rawUserText, options, sendModel);
17903
+ if ("tripwireRun" in gated) return gated.tripwireRun;
17904
+ const { userText, effectiveMessage } = gated;
17666
17905
  if (inputs.options.onBeforeSend !== void 0) {
17667
17906
  await inputs.options.onBeforeSend({
17668
17907
  conversationId: inputs.agentId,
@@ -17674,7 +17913,7 @@ async function executeSendLocked(inputs, message, options) {
17674
17913
  pluginManager: inputs.pluginManagerCode,
17675
17914
  agentId: inputs.agentId,
17676
17915
  options: inputs.options,
17677
- original: message,
17916
+ original: effectiveMessage,
17678
17917
  userText,
17679
17918
  sendOptions: options
17680
17919
  });
@@ -17712,11 +17951,18 @@ async function executeSendLocked(inputs, message, options) {
17712
17951
  memoryTools,
17713
17952
  effectiveMemoryProvider
17714
17953
  );
17954
+ const outputProcessors = inputs.options.outputProcessors;
17955
+ const processedRun = outputProcessors !== void 0 && outputProcessors.length > 0 ? wrapRunWithOutputProcessors({
17956
+ run,
17957
+ processors: outputProcessors,
17958
+ agentId: inputs.agentId,
17959
+ onRunEvent: options.onRunEvent
17960
+ }) : run;
17715
17961
  return wrapRunWithPostReplyHook({
17716
17962
  pluginManager: inputs.pluginManagerCode,
17717
17963
  agentId: inputs.agentId,
17718
17964
  options: inputs.options,
17719
- run,
17965
+ run: processedRun,
17720
17966
  userText
17721
17967
  });
17722
17968
  }
@@ -17965,7 +18211,7 @@ var LocalAgent = class {
17965
18211
  }
17966
18212
  // biome-ignore format: G8 budget — thin accessor for the assembly inputs.
17967
18213
  assemblyInputs() {
17968
- return { agentId: this.agentId, workspaceCwd: this.workspaceCwd, model: this.model, options: this.options, context: this.context, skillsManager: this.skillsManager, systemPromptPipeline: this.systemPromptPipeline };
18214
+ 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 };
17969
18215
  }
17970
18216
  async resolveSystemPrompt(userText, options, memoryFacts) {
17971
18217
  const base = await resolveSystemPromptForSend(
@@ -19075,6 +19321,48 @@ var Budget = class {
19075
19321
  }
19076
19322
  };
19077
19323
 
19324
+ // src/built-in-processors.ts
19325
+ var CHARS_PER_TOKEN = 4;
19326
+ function estimateTokens(text) {
19327
+ return Math.ceil(text.length / CHARS_PER_TOKEN);
19328
+ }
19329
+ var CONTROL_CHARS = /[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]/g;
19330
+ function createUnicodeNormalizer(opts = {}) {
19331
+ const stripControlChars = opts.stripControlChars ?? false;
19332
+ const collapseWhitespace = opts.collapseWhitespace ?? false;
19333
+ return {
19334
+ id: "unicode-normalizer",
19335
+ processInput(ctx) {
19336
+ let s = ctx.message.normalize("NFC");
19337
+ if (stripControlChars) s = s.replace(CONTROL_CHARS, "");
19338
+ if (collapseWhitespace) {
19339
+ s = s.replace(/[^\S\n]+/g, " ").replace(/ *\n */g, "\n").replace(/\n{3,}/g, "\n\n").trim();
19340
+ }
19341
+ return s;
19342
+ }
19343
+ };
19344
+ }
19345
+ function createTokenLimiter(opts) {
19346
+ if (!Number.isInteger(opts.limit) || opts.limit <= 0) {
19347
+ throw new Error("createTokenLimiter: `limit` must be a positive integer.");
19348
+ }
19349
+ const limit = opts.limit;
19350
+ const strategy = opts.strategy ?? "truncate";
19351
+ const cap2 = (text, controls) => {
19352
+ const estimated = estimateTokens(text);
19353
+ if (estimated <= limit) return text;
19354
+ if (strategy === "block") {
19355
+ controls.abort(`exceeds token limit ${limit} (~${estimated} estimated)`);
19356
+ }
19357
+ return [...text].slice(0, limit * CHARS_PER_TOKEN).join("");
19358
+ };
19359
+ return {
19360
+ id: "token-limiter",
19361
+ processInput: (ctx) => cap2(ctx.message, ctx),
19362
+ processOutput: (ctx) => cap2(ctx.text, ctx)
19363
+ };
19364
+ }
19365
+
19078
19366
  // src/create-skill.ts
19079
19367
  function createSkill(spec) {
19080
19368
  if (!spec.name) throw new Error("createSkill: `name` is required.");
@@ -19085,7 +19373,8 @@ function createSkill(spec) {
19085
19373
  source: `inline://${spec.name}`,
19086
19374
  instructions: spec.instructions,
19087
19375
  ...spec.category !== void 0 ? { category: spec.category } : {},
19088
- ...spec.dependencies !== void 0 ? { dependencies: spec.dependencies } : {}
19376
+ ...spec.dependencies !== void 0 ? { dependencies: spec.dependencies } : {},
19377
+ ...spec.references !== void 0 ? { references: spec.references } : {}
19089
19378
  };
19090
19379
  }
19091
19380
 
@@ -19512,6 +19801,46 @@ function defineProvider(profile, opts) {
19512
19801
  };
19513
19802
  }
19514
19803
 
19804
+ // src/define-skill-read-tool.ts
19805
+ init_to_json_schema();
19806
+ var SkillReadInputSchema = z.object({
19807
+ name: z.string().min(1, "skill_read: `name` is required.")
19808
+ });
19809
+ function renderSkill(skill) {
19810
+ const parts = [`# Skill: ${skill.name}`, "", skill.instructions];
19811
+ const refs = skill.references;
19812
+ if (refs !== void 0 && Object.keys(refs).length > 0) {
19813
+ parts.push("", "## References");
19814
+ for (const [file, content] of Object.entries(refs)) {
19815
+ parts.push("", `### ${file}`, content);
19816
+ }
19817
+ }
19818
+ return parts.join("\n");
19819
+ }
19820
+ function defineSkillReadTool(skills) {
19821
+ const seen = /* @__PURE__ */ new Set();
19822
+ for (const skill of skills) {
19823
+ if (seen.has(skill.name)) {
19824
+ throw new Error(`defineSkillReadTool: duplicate skill name "${skill.name}".`);
19825
+ }
19826
+ seen.add(skill.name);
19827
+ }
19828
+ return {
19829
+ name: "skill_read",
19830
+ 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.",
19831
+ inputSchema: toJsonSchema(SkillReadInputSchema),
19832
+ handler: (input) => {
19833
+ const { name } = SkillReadInputSchema.parse(input);
19834
+ const skill = skills.find((s) => s.name === name);
19835
+ if (skill === void 0) {
19836
+ const available = skills.map((s) => s.name).join(", ");
19837
+ return `Skill "${name}" not found. Available skills: ${available.length > 0 ? available : "(none)"}.`;
19838
+ }
19839
+ return renderSkill(skill);
19840
+ }
19841
+ };
19842
+ }
19843
+
19515
19844
  // src/define-tool.ts
19516
19845
  init_to_json_schema();
19517
19846
  function shapeToolResult(spec, out) {
@@ -19715,7 +20044,7 @@ function createCounterBudgetTracker(options = {}) {
19715
20044
  }
19716
20045
 
19717
20046
  // src/internal/runtime/context/replay-history.ts
19718
- var CHARS_PER_TOKEN = 4;
20047
+ var CHARS_PER_TOKEN2 = 4;
19719
20048
  var DEFAULT_RESERVE_TOKENS = 8e3;
19720
20049
  function finiteOr(value, fallback) {
19721
20050
  return Number.isFinite(value) ? value : fallback;
@@ -19723,7 +20052,7 @@ function finiteOr(value, fallback) {
19723
20052
  function charBudget(options) {
19724
20053
  const window = finiteOr(options.contextWindowTokens, 0);
19725
20054
  const reserve = finiteOr(options.reserveTokens ?? DEFAULT_RESERVE_TOKENS, DEFAULT_RESERVE_TOKENS);
19726
- return Math.max(0, window - reserve) * CHARS_PER_TOKEN;
20055
+ return Math.max(0, window - reserve) * CHARS_PER_TOKEN2;
19727
20056
  }
19728
20057
  function assistantText2(event) {
19729
20058
  return event.message.content.filter((block) => block.type === "text").map((block) => block.text).join("");
@@ -21409,6 +21738,6 @@ function safeStringify2(v) {
21409
21738
  }
21410
21739
  }
21411
21740
 
21412
- export { Agent, AgentBuilder, AgentDisposedError, AgentRunError, AuthenticationError, Budget, BudgetExceededError, ConfigurationError, Cron, EventBus, FileSystemConversationStorage, GenerateObjectError, InMemoryConversationStorage, IntegrationNotConnectedError, InvalidTaskIdError, JobQueue, Memory, MemoryAdapterError, NetworkError, PermissionEngine, RateLimitError, Security, StreamObjectError, Task, TaskNotFoundError, Theokit, TheokitAgentError, ToolError, UnknownAgentError, UnsupportedBudgetOperationError, UnsupportedRunOperationError, UnsupportedTaskOperationError, UsageAccumulator, applyMode, buildReplayHistory, chargeAndCheckThresholds, computeCost, createAgentFactory, createCounterBudgetTracker, createNoopMemoryProvider, createPermissionPlugin, createSessionManager, createSkill, createSquad, definePlugin, defineProvider, defineTool, emitRunEvent, extractRawId, getPricingEntry, inferApiMode, isTransientError, migrateSqliteToLance2 as migrateSqliteToLance, mkMemoryId, normalizeSchema, normalizeUsage, preflightCheck, scopedConversationId, sessionScopePrefix, toShareGptTrajectory, withCwdMutex };
21741
+ export { Agent, AgentBuilder, AgentDisposedError, AgentRunError, AuthenticationError, Budget, BudgetExceededError, ConfigurationError, Cron, EventBus, FileSystemConversationStorage, GenerateObjectError, InMemoryConversationStorage, IntegrationNotConnectedError, InvalidTaskIdError, JobQueue, Memory, MemoryAdapterError, NetworkError, PermissionEngine, RateLimitError, Security, StreamObjectError, Task, TaskNotFoundError, Theokit, TheokitAgentError, ToolError, UnknownAgentError, UnsupportedBudgetOperationError, UnsupportedRunOperationError, UnsupportedTaskOperationError, UsageAccumulator, applyMode, buildReplayHistory, chargeAndCheckThresholds, computeCost, createAgentFactory, createCounterBudgetTracker, createNoopMemoryProvider, createPermissionPlugin, createSessionManager, createSkill, createSquad, createTokenLimiter, createUnicodeNormalizer, definePlugin, defineProvider, defineSkillReadTool, defineTool, emitRunEvent, estimateTokens, extractRawId, getPricingEntry, inferApiMode, isTransientError, migrateSqliteToLance2 as migrateSqliteToLance, mkMemoryId, normalizeSchema, normalizeUsage, preflightCheck, scopedConversationId, sessionScopePrefix, toShareGptTrajectory, withCwdMutex };
21413
21742
  //# sourceMappingURL=index.js.map
21414
21743
  //# sourceMappingURL=index.js.map