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