@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/cron.js CHANGED
@@ -3459,7 +3459,8 @@ function stripSecretsFromOptions(options) {
3459
3459
  local: serializeLocal(options.local),
3460
3460
  cloud: serializeCloud(options.cloud),
3461
3461
  memory: serializeMemory(options.memory),
3462
- skills: serializeEnabledList(options.skills),
3462
+ // SE22 — a SkillsResolver function isn't serializable; persist only the static form.
3463
+ skills: serializeEnabledList(typeof options.skills === "function" ? void 0 : options.skills),
3463
3464
  // Code-`Plugin` objects are closures and cannot be persisted (like custom
3464
3465
  // tools); only the named-enable settings form is serialized.
3465
3466
  plugins: serializeEnabledList(asPluginsSettings(options.plugins)),
@@ -3767,6 +3768,7 @@ function serializeCloud2(cloud) {
3767
3768
  return result;
3768
3769
  }
3769
3770
  function serializeSkills(skills) {
3771
+ if (typeof skills === "function") return void 0;
3770
3772
  if (skills?.enabled === void 0 || skills.enabled.length === 0) return void 0;
3771
3773
  return { enabled: [...skills.enabled] };
3772
3774
  }
@@ -5238,8 +5240,19 @@ init_errors();
5238
5240
  function validateCloudToolParity(options) {
5239
5241
  if (options.cloud === void 0) return;
5240
5242
  rejectFunctionSystemPrompt(options);
5243
+ rejectFunctionSkills(options);
5244
+ rejectProcessors(options);
5241
5245
  rejectStdioMcpLocalPaths(options);
5242
5246
  }
5247
+ function rejectProcessors(options) {
5248
+ const hasProcessors = (options.inputProcessors?.length ?? 0) > 0 || (options.outputProcessors?.length ?? 0) > 0;
5249
+ if (hasProcessors) {
5250
+ throw new ConfigurationError(
5251
+ "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.",
5252
+ { code: "cloud_incompatible_function_resolver" }
5253
+ );
5254
+ }
5255
+ }
5243
5256
  function rejectFunctionSystemPrompt(options) {
5244
5257
  if (typeof options.systemPrompt === "function") {
5245
5258
  throw new ConfigurationError(
@@ -5248,6 +5261,14 @@ function rejectFunctionSystemPrompt(options) {
5248
5261
  );
5249
5262
  }
5250
5263
  }
5264
+ function rejectFunctionSkills(options) {
5265
+ if (typeof options.skills === "function") {
5266
+ throw new ConfigurationError(
5267
+ "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.",
5268
+ { code: "cloud_incompatible_function_resolver" }
5269
+ );
5270
+ }
5271
+ }
5251
5272
  function rejectStdioMcpLocalPaths(options) {
5252
5273
  if (options.mcpServers === void 0) return;
5253
5274
  for (const [name, config] of Object.entries(options.mcpServers)) {
@@ -7104,9 +7125,223 @@ function parseFrontmatterFields(frontmatter) {
7104
7125
  return out;
7105
7126
  }
7106
7127
 
7128
+ // src/internal/runtime/skills/discover-skills.ts
7129
+ init_errors();
7130
+
7131
+ // src/internal/runtime/skills/skill-frontmatter.ts
7132
+ init_errors();
7133
+ init_yaml_frontmatter();
7134
+ function asString(v) {
7135
+ return typeof v === "string" ? v : void 0;
7136
+ }
7137
+ function toStringFields(raw) {
7138
+ const out = {};
7139
+ for (const [k, v] of Object.entries(raw)) out[k] = asString(v);
7140
+ return out;
7141
+ }
7142
+ function parseSkillFrontmatter(raw, fallbackName) {
7143
+ const fields = extractAndParseFrontmatter(raw, fallbackName);
7144
+ const name = resolveName(fields, fallbackName);
7145
+ ensureRequiredFields(fields, name);
7146
+ return buildFrontmatter(fields, name);
7147
+ }
7148
+ function stripSkillFrontmatter(raw) {
7149
+ const match = /^---\s*\n[\s\S]*?\n---\s*\n/.exec(raw);
7150
+ return (match === null ? raw : raw.slice(match[0].length)).trim();
7151
+ }
7152
+ function extractAndParseFrontmatter(raw, fallbackName) {
7153
+ const match = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(raw);
7154
+ if (match === null) {
7155
+ throw new ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {
7156
+ code: "missing_frontmatter"
7157
+ });
7158
+ }
7159
+ const frontmatter = match[1] ?? "";
7160
+ try {
7161
+ return toStringFields(parseSimpleYaml(frontmatter));
7162
+ } catch (cause) {
7163
+ const detail = cause instanceof Error ? cause.message : String(cause);
7164
+ throw new ConfigurationError(
7165
+ `Skill ${fallbackName} has malformed YAML frontmatter: ${detail}`,
7166
+ { code: "schema_invalid", cause }
7167
+ );
7168
+ }
7169
+ }
7170
+ function resolveName(fields, fallbackName) {
7171
+ if (hasContent(fields.name)) return fields.name;
7172
+ if (hasContent(fallbackName)) return fallbackName;
7173
+ throw new ConfigurationError("Skill at unknown path is missing required field: name", {
7174
+ code: "schema_invalid"
7175
+ });
7176
+ }
7177
+ function ensureRequiredFields(fields, name) {
7178
+ if (!hasContent(fields.description)) {
7179
+ throw new ConfigurationError(`Skill ${name} is missing required field: description`, {
7180
+ code: "schema_invalid"
7181
+ });
7182
+ }
7183
+ }
7184
+ function buildFrontmatter(fields, name) {
7185
+ const description = fields.description;
7186
+ if (description === void 0) {
7187
+ throw new ConfigurationError(`Skill ${name} missing description`, { code: "schema_invalid" });
7188
+ }
7189
+ const result = { name, description };
7190
+ if (hasContent(fields.category)) result.category = fields.category;
7191
+ const deps = parseDependencies(fields.dependencies);
7192
+ if (deps !== void 0) result.dependencies = deps;
7193
+ return result;
7194
+ }
7195
+ function parseDependencies(raw) {
7196
+ if (!hasContent(raw)) return void 0;
7197
+ const deps = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
7198
+ return deps.length > 0 ? deps : void 0;
7199
+ }
7200
+ function hasContent(value) {
7201
+ return value !== void 0 && value.trim().length > 0;
7202
+ }
7203
+
7204
+ // src/internal/runtime/skills/discover-skills.ts
7205
+ async function discoverSkills(dir, options) {
7206
+ let entries;
7207
+ try {
7208
+ entries = await readWorkspaceDir(dir, "skills_read_error", "skills directory");
7209
+ } catch {
7210
+ return [];
7211
+ }
7212
+ const skills = [];
7213
+ for (const entry of entries) {
7214
+ if (!entry.isDirectory()) continue;
7215
+ let skillDir;
7216
+ try {
7217
+ skillDir = safePathJoin(dir, entry.name);
7218
+ assertNoSymlinkEscape(skillDir, dir);
7219
+ } catch {
7220
+ continue;
7221
+ }
7222
+ const skillPath = join(skillDir, "SKILL.md");
7223
+ let raw;
7224
+ try {
7225
+ raw = await readFile(skillPath, "utf8");
7226
+ } catch {
7227
+ continue;
7228
+ }
7229
+ const skill = tryParseSkill(raw, entry.name, skillPath, options);
7230
+ if (skill !== void 0) skills.push(skill);
7231
+ }
7232
+ return skills;
7233
+ }
7234
+ function tryParseSkill(raw, fallbackName, source, options) {
7235
+ try {
7236
+ const frontmatter = parseSkillFrontmatter(raw, fallbackName);
7237
+ const skill = {
7238
+ name: frontmatter.name,
7239
+ description: frontmatter.description,
7240
+ source
7241
+ };
7242
+ if (frontmatter.category !== void 0) skill.category = frontmatter.category;
7243
+ if (frontmatter.dependencies !== void 0) skill.dependencies = frontmatter.dependencies;
7244
+ return skill;
7245
+ } catch (cause) {
7246
+ if (cause instanceof ConfigurationError) {
7247
+ options?.onInvalidSkill?.({
7248
+ name: fallbackName,
7249
+ source,
7250
+ code: cause.code ?? "unknown",
7251
+ message: cause.message
7252
+ });
7253
+ return void 0;
7254
+ }
7255
+ throw cause;
7256
+ }
7257
+ }
7258
+
7259
+ // src/internal/runtime/skills/skills-manager.ts
7260
+ var SkillsManager = class {
7261
+ constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
7262
+ this.cwd = cwd;
7263
+ this.settingSourcesIncludeProject = settingSourcesIncludeProject;
7264
+ this.skillsDir = skillsDir;
7265
+ this.inline = inline;
7266
+ }
7267
+ cwd;
7268
+ settingSourcesIncludeProject;
7269
+ skillsDir;
7270
+ inline;
7271
+ skills = [];
7272
+ async initialize() {
7273
+ if (!this.settingSourcesIncludeProject) {
7274
+ this.skills = this.mergeInline([]);
7275
+ return;
7276
+ }
7277
+ await this.refresh();
7278
+ }
7279
+ async refresh() {
7280
+ const skillsRoot = this.skillsDir ?? join(this.cwd, ".theokit", "skills");
7281
+ const discovered = await discoverSkills(skillsRoot, {
7282
+ onInvalidSkill: (info) => {
7283
+ process.stderr.write(
7284
+ `[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
7285
+ `
7286
+ );
7287
+ }
7288
+ });
7289
+ this.skills = this.mergeInline(discovered);
7290
+ }
7291
+ /** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
7292
+ mergeInline(discovered) {
7293
+ if (this.inline === void 0 || this.inline.length === 0) return discovered;
7294
+ const inlineNames = new Set(this.inline.map((s) => s.name));
7295
+ return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
7296
+ }
7297
+ list() {
7298
+ return Promise.resolve(this.skills);
7299
+ }
7300
+ /**
7301
+ * SE20 — resolve a skill by name INCLUDING its body. Inline (`createSkill`)
7302
+ * skills carry `instructions` on the object; filesystem skills read the body
7303
+ * from their `source` SKILL.md (frontmatter stripped). `undefined` when no
7304
+ * enabled skill matches (malformed skills were already excluded at discovery).
7305
+ */
7306
+ async get(name) {
7307
+ const skill = this.skills.find((s) => s.name === name);
7308
+ if (skill === void 0) return void 0;
7309
+ const instructions = typeof skill.instructions === "string" ? skill.instructions : stripSkillFrontmatter(await readFile(skill.source, "utf8"));
7310
+ const references = skill.references;
7311
+ return {
7312
+ name: skill.name,
7313
+ description: skill.description,
7314
+ instructions,
7315
+ ...references !== void 0 ? { references } : {}
7316
+ };
7317
+ }
7318
+ };
7319
+
7107
7320
  // src/internal/runtime/system-prompt/local-assembly.ts
7108
- async function buildSystemPromptContext(inputs, userText, memoryFacts) {
7109
- const skills = inputs.skillsManager !== void 0 ? await inputs.skillsManager.list() : [];
7321
+ async function resolveSendSkills(inputs, userText, memoryFacts) {
7322
+ const skills = inputs.options.skills;
7323
+ if (typeof skills !== "function") {
7324
+ return { manager: inputs.skillsManager, autoInject: skills?.autoInject ?? true };
7325
+ }
7326
+ const settings = await skills({
7327
+ agentId: inputs.agentId,
7328
+ cwd: inputs.workspaceCwd,
7329
+ model: inputs.model,
7330
+ userMessage: userText,
7331
+ memory: memoryFacts.map((fact) => ({ text: fact.text }))
7332
+ });
7333
+ const manager = new SkillsManager(
7334
+ inputs.workspaceCwd,
7335
+ settings.enabled,
7336
+ inputs.settingSourcesIncludeProject,
7337
+ settings.skillsDir,
7338
+ settings.inline
7339
+ );
7340
+ await manager.initialize();
7341
+ return { manager, autoInject: settings.autoInject ?? true };
7342
+ }
7343
+ async function buildSystemPromptContext(inputs, userText, memoryFacts, manager = inputs.skillsManager) {
7344
+ const skills = manager !== void 0 ? await manager.list() : [];
7110
7345
  return {
7111
7346
  agentId: inputs.agentId,
7112
7347
  cwd: inputs.workspaceCwd,
@@ -7117,10 +7352,11 @@ async function buildSystemPromptContext(inputs, userText, memoryFacts) {
7117
7352
  };
7118
7353
  }
7119
7354
  async function buildAssemblyContext(inputs, userText, baseSystemPrompt, memoryFacts, activeMemorySummary) {
7120
- const baseCtx = await buildSystemPromptContext(inputs, userText, memoryFacts);
7355
+ const resolved = await resolveSendSkills(inputs, userText, memoryFacts);
7356
+ const baseCtx = await buildSystemPromptContext(inputs, userText, memoryFacts, resolved.manager);
7121
7357
  const assemblyCtx = {
7122
7358
  ...baseCtx,
7123
- skillsAutoInject: inputs.options.skills?.autoInject ?? true,
7359
+ skillsAutoInject: resolved.autoInject,
7124
7360
  memoryAutoInject: inputs.options.memory?.autoInject ?? true
7125
7361
  };
7126
7362
  if (baseSystemPrompt !== void 0) assemblyCtx.baseSystemPrompt = baseSystemPrompt;
@@ -8372,176 +8608,6 @@ async function loadPluginManifestFromMarkdown(pluginsRoot, folderName) {
8372
8608
  return metadata;
8373
8609
  }
8374
8610
 
8375
- // src/internal/runtime/skills/discover-skills.ts
8376
- init_errors();
8377
-
8378
- // src/internal/runtime/skills/skill-frontmatter.ts
8379
- init_errors();
8380
- init_yaml_frontmatter();
8381
- function asString(v) {
8382
- return typeof v === "string" ? v : void 0;
8383
- }
8384
- function toStringFields(raw) {
8385
- const out = {};
8386
- for (const [k, v] of Object.entries(raw)) out[k] = asString(v);
8387
- return out;
8388
- }
8389
- function parseSkillFrontmatter(raw, fallbackName) {
8390
- const fields = extractAndParseFrontmatter(raw, fallbackName);
8391
- const name = resolveName(fields, fallbackName);
8392
- ensureRequiredFields(fields, name);
8393
- return buildFrontmatter(fields, name);
8394
- }
8395
- function extractAndParseFrontmatter(raw, fallbackName) {
8396
- const match = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(raw);
8397
- if (match === null) {
8398
- throw new ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {
8399
- code: "missing_frontmatter"
8400
- });
8401
- }
8402
- const frontmatter = match[1] ?? "";
8403
- try {
8404
- return toStringFields(parseSimpleYaml(frontmatter));
8405
- } catch (cause) {
8406
- const detail = cause instanceof Error ? cause.message : String(cause);
8407
- throw new ConfigurationError(
8408
- `Skill ${fallbackName} has malformed YAML frontmatter: ${detail}`,
8409
- { code: "schema_invalid", cause }
8410
- );
8411
- }
8412
- }
8413
- function resolveName(fields, fallbackName) {
8414
- if (hasContent(fields.name)) return fields.name;
8415
- if (hasContent(fallbackName)) return fallbackName;
8416
- throw new ConfigurationError("Skill at unknown path is missing required field: name", {
8417
- code: "schema_invalid"
8418
- });
8419
- }
8420
- function ensureRequiredFields(fields, name) {
8421
- if (!hasContent(fields.description)) {
8422
- throw new ConfigurationError(`Skill ${name} is missing required field: description`, {
8423
- code: "schema_invalid"
8424
- });
8425
- }
8426
- }
8427
- function buildFrontmatter(fields, name) {
8428
- const description = fields.description;
8429
- if (description === void 0) {
8430
- throw new ConfigurationError(`Skill ${name} missing description`, { code: "schema_invalid" });
8431
- }
8432
- const result = { name, description };
8433
- if (hasContent(fields.category)) result.category = fields.category;
8434
- const deps = parseDependencies(fields.dependencies);
8435
- if (deps !== void 0) result.dependencies = deps;
8436
- return result;
8437
- }
8438
- function parseDependencies(raw) {
8439
- if (!hasContent(raw)) return void 0;
8440
- const deps = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
8441
- return deps.length > 0 ? deps : void 0;
8442
- }
8443
- function hasContent(value) {
8444
- return value !== void 0 && value.trim().length > 0;
8445
- }
8446
-
8447
- // src/internal/runtime/skills/discover-skills.ts
8448
- async function discoverSkills(dir, options) {
8449
- let entries;
8450
- try {
8451
- entries = await readWorkspaceDir(dir, "skills_read_error", "skills directory");
8452
- } catch {
8453
- return [];
8454
- }
8455
- const skills = [];
8456
- for (const entry of entries) {
8457
- if (!entry.isDirectory()) continue;
8458
- let skillDir;
8459
- try {
8460
- skillDir = safePathJoin(dir, entry.name);
8461
- assertNoSymlinkEscape(skillDir, dir);
8462
- } catch {
8463
- continue;
8464
- }
8465
- const skillPath = join(skillDir, "SKILL.md");
8466
- let raw;
8467
- try {
8468
- raw = await readFile(skillPath, "utf8");
8469
- } catch {
8470
- continue;
8471
- }
8472
- const skill = tryParseSkill(raw, entry.name, skillPath, options);
8473
- if (skill !== void 0) skills.push(skill);
8474
- }
8475
- return skills;
8476
- }
8477
- function tryParseSkill(raw, fallbackName, source, options) {
8478
- try {
8479
- const frontmatter = parseSkillFrontmatter(raw, fallbackName);
8480
- const skill = {
8481
- name: frontmatter.name,
8482
- description: frontmatter.description,
8483
- source
8484
- };
8485
- if (frontmatter.category !== void 0) skill.category = frontmatter.category;
8486
- if (frontmatter.dependencies !== void 0) skill.dependencies = frontmatter.dependencies;
8487
- return skill;
8488
- } catch (cause) {
8489
- if (cause instanceof ConfigurationError) {
8490
- options?.onInvalidSkill?.({
8491
- name: fallbackName,
8492
- source,
8493
- code: cause.code ?? "unknown",
8494
- message: cause.message
8495
- });
8496
- return void 0;
8497
- }
8498
- throw cause;
8499
- }
8500
- }
8501
-
8502
- // src/internal/runtime/skills/skills-manager.ts
8503
- var SkillsManager = class {
8504
- constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
8505
- this.cwd = cwd;
8506
- this.settingSourcesIncludeProject = settingSourcesIncludeProject;
8507
- this.skillsDir = skillsDir;
8508
- this.inline = inline;
8509
- }
8510
- cwd;
8511
- settingSourcesIncludeProject;
8512
- skillsDir;
8513
- inline;
8514
- skills = [];
8515
- async initialize() {
8516
- if (!this.settingSourcesIncludeProject) {
8517
- this.skills = this.mergeInline([]);
8518
- return;
8519
- }
8520
- await this.refresh();
8521
- }
8522
- async refresh() {
8523
- const skillsRoot = this.skillsDir ?? join(this.cwd, ".theokit", "skills");
8524
- const discovered = await discoverSkills(skillsRoot, {
8525
- onInvalidSkill: (info) => {
8526
- process.stderr.write(
8527
- `[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
8528
- `
8529
- );
8530
- }
8531
- });
8532
- this.skills = this.mergeInline(discovered);
8533
- }
8534
- /** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
8535
- mergeInline(discovered) {
8536
- if (this.inline === void 0 || this.inline.length === 0) return discovered;
8537
- const inlineNames = new Set(this.inline.map((s) => s.name));
8538
- return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
8539
- }
8540
- list() {
8541
- return Promise.resolve(this.skills);
8542
- }
8543
- };
8544
-
8545
8611
  // src/internal/runtime/local-agent/local-agent-bootstrap.ts
8546
8612
  function registerLocalAgent(args) {
8547
8613
  registerAgent({
@@ -8577,16 +8643,23 @@ function bootstrapSubmanagers(args) {
8577
8643
  );
8578
8644
  }
8579
8645
  if (args.options.skills !== void 0 || args.settingSourcesIncludeProject) {
8646
+ const staticSkills = typeof args.options.skills === "function" ? void 0 : args.options.skills;
8580
8647
  out.skillsManager = new SkillsManager(
8581
8648
  args.workspaceCwd,
8582
- args.options.skills?.enabled,
8649
+ staticSkills?.enabled,
8583
8650
  args.settingSourcesIncludeProject,
8584
8651
  // M22 — custom skills directory + inline (code-defined) skills.
8585
- args.options.skills?.skillsDir,
8586
- args.options.skills?.inline
8652
+ staticSkills?.skillsDir,
8653
+ staticSkills?.inline
8587
8654
  );
8588
8655
  const localSkills = out.skillsManager;
8589
- out.skills = { list: () => localSkills.list() };
8656
+ out.skills = {
8657
+ // Project to the public shape (name + description only). Inline skills carry
8658
+ // their body + references on the object; `list()` must never leak them —
8659
+ // the body is reachable exclusively through `get()`.
8660
+ list: async () => (await localSkills.list()).map((s) => ({ name: s.name, description: s.description })),
8661
+ get: (name) => localSkills.get(name)
8662
+ };
8590
8663
  }
8591
8664
  if (args.options.plugins !== void 0 || args.settingSourcesIncludePlugins) {
8592
8665
  out.pluginsManager = new PluginsManager(
@@ -16078,6 +16151,145 @@ function ponyfillAny(signals) {
16078
16151
  return ctrl.signal;
16079
16152
  }
16080
16153
 
16154
+ // src/internal/runtime/processors/run-processors.ts
16155
+ var ProcessorAbort = class {
16156
+ constructor(processorId, reason) {
16157
+ this.processorId = processorId;
16158
+ this.reason = reason;
16159
+ }
16160
+ processorId;
16161
+ reason;
16162
+ };
16163
+ function fireViolation(processor, violation) {
16164
+ try {
16165
+ processor.onViolation?.(violation);
16166
+ } catch {
16167
+ }
16168
+ }
16169
+ function controlsFor(processor) {
16170
+ return {
16171
+ abort(reason) {
16172
+ throw new ProcessorAbort(processor.id, reason);
16173
+ },
16174
+ warn(message, detail) {
16175
+ fireViolation(processor, {
16176
+ processorId: processor.id,
16177
+ message,
16178
+ ...detail !== void 0 ? { detail } : {}
16179
+ });
16180
+ }
16181
+ };
16182
+ }
16183
+ function selectHandler(processor, phase) {
16184
+ if (phase === "input") {
16185
+ return processor.processInput ? { kind: "input", fn: processor.processInput } : void 0;
16186
+ }
16187
+ return processor.processOutput ? { kind: "output", fn: processor.processOutput } : void 0;
16188
+ }
16189
+ function invokeHandler(handler, value, agentId, controls) {
16190
+ return handler.kind === "input" ? handler.fn({ message: value, agentId, ...controls }) : handler.fn({ text: value, agentId, ...controls });
16191
+ }
16192
+ async function runOneProcessor(processor, value, agentId, phase) {
16193
+ const handler = selectHandler(processor, phase);
16194
+ if (handler === void 0) return { value };
16195
+ try {
16196
+ const out = await invokeHandler(handler, value, agentId, controlsFor(processor));
16197
+ return { value: typeof out === "string" ? out : value };
16198
+ } catch (err) {
16199
+ if (!(err instanceof ProcessorAbort)) throw err;
16200
+ fireViolation(processor, { processorId: err.processorId, message: err.reason });
16201
+ return { tripwire: { reason: err.reason, processorId: err.processorId } };
16202
+ }
16203
+ }
16204
+ async function runPipeline(processors, initial, agentId, phase) {
16205
+ let value = initial;
16206
+ for (const processor of processors) {
16207
+ const step = await runOneProcessor(processor, value, agentId, phase);
16208
+ if ("tripwire" in step) return { kind: "tripwire", tripwire: step.tripwire };
16209
+ value = step.value;
16210
+ }
16211
+ return { kind: "ok", value };
16212
+ }
16213
+ function runInputProcessors(processors, message, agentId) {
16214
+ return runPipeline(processors, message, agentId, "input");
16215
+ }
16216
+ function runOutputProcessors(processors, text, agentId) {
16217
+ return runPipeline(processors, text, agentId, "output");
16218
+ }
16219
+
16220
+ // src/internal/runtime/processors/tripwire-run.ts
16221
+ var SUPPORTED = /* @__PURE__ */ new Set([
16222
+ "stream",
16223
+ "wait",
16224
+ "cancel",
16225
+ "conversation"
16226
+ ]);
16227
+ function emptyStream() {
16228
+ return {
16229
+ next: () => Promise.resolve({ done: true, value: void 0 }),
16230
+ return: () => Promise.resolve({ done: true, value: void 0 }),
16231
+ throw: (err) => Promise.reject(err),
16232
+ [Symbol.asyncIterator]() {
16233
+ return this;
16234
+ }
16235
+ };
16236
+ }
16237
+ function createTripwireRun(args) {
16238
+ const id = globalThis.crypto.randomUUID();
16239
+ const result = {
16240
+ id,
16241
+ status: "cancelled",
16242
+ tripwire: args.tripwire,
16243
+ ...args.model !== void 0 ? { model: args.model } : {}
16244
+ };
16245
+ const run = {
16246
+ id,
16247
+ agentId: args.agentId,
16248
+ status: "cancelled",
16249
+ ...args.model !== void 0 ? { model: args.model } : {},
16250
+ stream: () => emptyStream(),
16251
+ wait: () => Promise.resolve(result),
16252
+ cancel: () => Promise.resolve(),
16253
+ conversation: () => Promise.resolve([]),
16254
+ supports: (op) => SUPPORTED.has(op),
16255
+ unsupportedReason: (op) => SUPPORTED.has(op) ? void 0 : `operation "${op}" is not available on a tripwire run`,
16256
+ onDidChangeStatus: () => () => {
16257
+ }
16258
+ // already terminal — status never changes
16259
+ };
16260
+ registerRun(run);
16261
+ return run;
16262
+ }
16263
+
16264
+ // src/internal/runtime/processors/wrap-output-run.ts
16265
+ function wrapRunWithOutputProcessors(args) {
16266
+ if (args.processors.length === 0) return args.run;
16267
+ const compute = async () => {
16268
+ const result = await args.run.wait();
16269
+ if (result.status !== "finished" || result.result === void 0) return result;
16270
+ const res = await runOutputProcessors(args.processors, result.result, args.agentId);
16271
+ if (res.kind === "ok") return { ...result, result: res.value };
16272
+ emitRunEvent(args.onRunEvent, {
16273
+ type: "tripwire",
16274
+ reason: res.tripwire.reason,
16275
+ processorId: res.tripwire.processorId
16276
+ });
16277
+ const { result: _suppressed, ...metadata } = result;
16278
+ return { ...metadata, status: "cancelled", tripwire: res.tripwire };
16279
+ };
16280
+ let processed;
16281
+ const wrappedWait = () => {
16282
+ processed ??= compute();
16283
+ return processed;
16284
+ };
16285
+ return new Proxy(args.run, {
16286
+ get(target, prop, receiver) {
16287
+ if (prop === "wait") return wrappedWait;
16288
+ return Reflect.get(target, prop, receiver);
16289
+ }
16290
+ });
16291
+ }
16292
+
16081
16293
  // src/internal/runtime/local-agent/local-agent-memory-hooks.ts
16082
16294
  var DEFAULT_MAX_RECALL_BYTES = 16e3;
16083
16295
  async function applyPreUserSendHook(args) {
@@ -16125,11 +16337,38 @@ function wrapRunWithPostReplyHook(args) {
16125
16337
  }
16126
16338
 
16127
16339
  // src/internal/runtime/local-agent/local-agent-send.ts
16340
+ async function applyInputProcessors(inputs, message, rawUserText, options, sendModel) {
16341
+ const processors = inputs.options.inputProcessors;
16342
+ if (processors === void 0 || processors.length === 0) {
16343
+ return { userText: rawUserText, effectiveMessage: message };
16344
+ }
16345
+ const res = await runInputProcessors(processors, rawUserText, inputs.agentId);
16346
+ if (res.kind === "tripwire") {
16347
+ emitRunEvent(options.onRunEvent, {
16348
+ type: "tripwire",
16349
+ reason: res.tripwire.reason,
16350
+ processorId: res.tripwire.processorId
16351
+ });
16352
+ return {
16353
+ tripwireRun: createTripwireRun({
16354
+ agentId: inputs.agentId,
16355
+ tripwire: res.tripwire,
16356
+ model: sendModel
16357
+ })
16358
+ };
16359
+ }
16360
+ const effectiveMessage = typeof message === "string" ? res.value : { ...message, text: res.value };
16361
+ return { userText: res.value, effectiveMessage };
16362
+ }
16128
16363
  async function executeSendLocked(inputs, message, options) {
16129
16364
  if (inputs.disposed) throw new AgentDisposedError(inputs.agentId);
16130
16365
  await consumePending(inputs.agentId, inputs.invalidationPending, inputs.clearInvalidation, inputs.reload);
16131
- inputs.applyModelOverride(normalizeModel(options.model));
16132
- const userText = typeof message === "string" ? message : message.text;
16366
+ const sendModel = normalizeModel(options.model);
16367
+ inputs.applyModelOverride(sendModel);
16368
+ const rawUserText = typeof message === "string" ? message : message.text;
16369
+ const gated = await applyInputProcessors(inputs, message, rawUserText, options, sendModel);
16370
+ if ("tripwireRun" in gated) return gated.tripwireRun;
16371
+ const { userText, effectiveMessage } = gated;
16133
16372
  if (inputs.options.onBeforeSend !== void 0) {
16134
16373
  await inputs.options.onBeforeSend({
16135
16374
  conversationId: inputs.agentId,
@@ -16141,7 +16380,7 @@ async function executeSendLocked(inputs, message, options) {
16141
16380
  pluginManager: inputs.pluginManagerCode,
16142
16381
  agentId: inputs.agentId,
16143
16382
  options: inputs.options,
16144
- original: message,
16383
+ original: effectiveMessage,
16145
16384
  userText,
16146
16385
  sendOptions: options
16147
16386
  });
@@ -16179,11 +16418,18 @@ async function executeSendLocked(inputs, message, options) {
16179
16418
  memoryTools,
16180
16419
  effectiveMemoryProvider
16181
16420
  );
16421
+ const outputProcessors = inputs.options.outputProcessors;
16422
+ const processedRun = outputProcessors !== void 0 && outputProcessors.length > 0 ? wrapRunWithOutputProcessors({
16423
+ run,
16424
+ processors: outputProcessors,
16425
+ agentId: inputs.agentId,
16426
+ onRunEvent: options.onRunEvent
16427
+ }) : run;
16182
16428
  return wrapRunWithPostReplyHook({
16183
16429
  pluginManager: inputs.pluginManagerCode,
16184
16430
  agentId: inputs.agentId,
16185
16431
  options: inputs.options,
16186
- run,
16432
+ run: processedRun,
16187
16433
  userText
16188
16434
  });
16189
16435
  }
@@ -16432,7 +16678,7 @@ var LocalAgent = class {
16432
16678
  }
16433
16679
  // biome-ignore format: G8 budget — thin accessor for the assembly inputs.
16434
16680
  assemblyInputs() {
16435
- return { agentId: this.agentId, workspaceCwd: this.workspaceCwd, model: this.model, options: this.options, context: this.context, skillsManager: this.skillsManager, systemPromptPipeline: this.systemPromptPipeline };
16681
+ 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 };
16436
16682
  }
16437
16683
  async resolveSystemPrompt(userText, options, memoryFacts) {
16438
16684
  const base = await resolveSystemPromptForSend(