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