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