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