@theokit/sdk 2.20.0 → 2.22.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 (92) hide show
  1. package/CHANGELOG.md +148 -0
  2. package/dist/a2a/index.cjs +673 -317
  3. package/dist/a2a/index.cjs.map +1 -1
  4. package/dist/a2a/index.d.cts +2 -1
  5. package/dist/a2a/index.d.ts +2 -1
  6. package/dist/a2a/index.js +674 -318
  7. package/dist/a2a/index.js.map +1 -1
  8. package/dist/a2a/subagent.d.cts +70 -1
  9. package/dist/a2a/subagent.d.ts +70 -1
  10. package/dist/a2a/types.d.cts +7 -0
  11. package/dist/a2a/types.d.ts +7 -0
  12. package/dist/agent-builder.d.ts +2 -1
  13. package/dist/agent-generate.d.ts +12 -0
  14. package/dist/client/index.cjs.map +1 -1
  15. package/dist/client/index.d.cts +5 -0
  16. package/dist/client/index.d.ts +5 -0
  17. package/dist/client/index.js.map +1 -1
  18. package/dist/client/theokit-client.d.cts +6 -0
  19. package/dist/client/theokit-client.d.ts +6 -0
  20. package/dist/client/types.d.cts +2 -0
  21. package/dist/client/types.d.ts +2 -0
  22. package/dist/{cron-B8fqui49.d.cts → cron-7CruUd_0.d.ts} +53 -3
  23. package/dist/{cron-D2yLOrk2.d.ts → cron-Bpt_1khA.d.cts} +53 -3
  24. package/dist/cron.cjs +654 -389
  25. package/dist/cron.cjs.map +1 -1
  26. package/dist/cron.d.cts +3 -2
  27. package/dist/cron.d.ts +3 -2
  28. package/dist/cron.js +655 -390
  29. package/dist/cron.js.map +1 -1
  30. package/dist/{errors-5lj1EWgs.d.ts → errors-BuwwkrAk.d.ts} +2 -2
  31. package/dist/{errors-CE-lMBi2.d.cts → errors-CkCaIqVP.d.cts} +2 -2
  32. package/dist/errors.d.cts +3 -2
  33. package/dist/eval.cjs +654 -389
  34. package/dist/eval.cjs.map +1 -1
  35. package/dist/eval.js +654 -389
  36. package/dist/eval.js.map +1 -1
  37. package/dist/generate-object.d.ts +4 -3
  38. package/dist/index.cjs +800 -392
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.cts +259 -17
  41. package/dist/index.d.ts +259 -17
  42. package/dist/index.js +798 -394
  43. package/dist/index.js.map +1 -1
  44. package/dist/internal/agent-loop/loop-types.d.ts +2 -0
  45. package/dist/internal/agent-loop/tool-result-guard.d.ts +1 -0
  46. package/dist/internal/llm/tool-result-content.d.ts +40 -0
  47. package/dist/internal/llm/types.d.ts +6 -1
  48. package/dist/internal/persistence/conversation-storage-fs.d.cts +3 -1
  49. package/dist/internal/persistence/conversation-storage-fs.d.ts +3 -1
  50. package/dist/internal/persistence/conversation-storage-memory.d.cts +3 -1
  51. package/dist/internal/persistence/conversation-storage-memory.d.ts +3 -1
  52. package/dist/internal/persistence/session-meta.d.cts +13 -0
  53. package/dist/internal/persistence/session-meta.d.ts +13 -0
  54. package/dist/internal/runtime/model-selection.d.ts +14 -0
  55. package/dist/internal/structured-output-helpers.d.ts +1 -1
  56. package/dist/permission-engine.d.ts +32 -1
  57. package/dist/{run-BgfBWX-z.d.cts → run-CrIulPF7.d.cts} +282 -19
  58. package/dist/{run-BgfBWX-z.d.ts → run-CrIulPF7.d.ts} +282 -19
  59. package/dist/stream-object.d.ts +2 -1
  60. package/dist/tool-error.d.ts +30 -0
  61. package/dist/types/agent-prims.d.ts +30 -8
  62. package/dist/types/agent.d.ts +13 -2
  63. package/dist/types/content-blocks.d.ts +47 -0
  64. package/dist/types/conversation-storage.d.ts +38 -0
  65. package/dist/types/index.d.ts +1 -0
  66. package/dist/types/messages.d.ts +2 -9
  67. package/dist/types/run-events.d.ts +84 -0
  68. package/dist/types/run.d.ts +115 -1
  69. package/dist/types/session.d.ts +99 -0
  70. package/dist/types/workflow.d.ts +7 -0
  71. package/dist/workflow.cjs +7 -2
  72. package/dist/workflow.cjs.map +1 -1
  73. package/dist/workflow.d.cts +2 -0
  74. package/dist/workflow.d.ts +2 -0
  75. package/dist/workflow.js +7 -2
  76. package/dist/workflow.js.map +1 -1
  77. package/package.json +14 -34
  78. package/dist/internal/observability/context.d.cts +0 -23
  79. package/dist/internal/observability/context.d.ts +0 -23
  80. package/dist/internal/observability/index.cjs +0 -38
  81. package/dist/internal/observability/index.cjs.map +0 -1
  82. package/dist/internal/observability/index.d.cts +0 -8
  83. package/dist/internal/observability/index.d.ts +0 -8
  84. package/dist/internal/observability/index.js +0 -33
  85. package/dist/internal/observability/index.js.map +0 -1
  86. package/dist/internal/plugins/index.cjs +0 -363
  87. package/dist/internal/plugins/index.cjs.map +0 -1
  88. package/dist/internal/plugins/index.js +0 -357
  89. package/dist/internal/plugins/index.js.map +0 -1
  90. package/dist/internal/workflow/index.d.ts +0 -12
  91. package/dist/server/adapter/index.d.cts +0 -8
  92. package/dist/server/adapter/index.d.ts +0 -8
@@ -2,11 +2,11 @@
2
2
 
3
3
  var fs = require('fs');
4
4
  var crypto = require('crypto');
5
+ var zod = require('zod');
6
+ var module$1 = require('module');
5
7
  var path = require('path');
6
8
  var promises = require('fs/promises');
7
9
  var os = require('os');
8
- var zod = require('zod');
9
- var module$1 = require('module');
10
10
  var child_process = require('child_process');
11
11
  var async_hooks = require('async_hooks');
12
12
  var url = require('url');
@@ -32,6 +32,7 @@ var init_agent_builder = __esm({
32
32
  constructor(deps) {
33
33
  this.deps = deps;
34
34
  }
35
+ /** SE8 — accepts a bare-string id shorthand (`"openai/gpt-4o-mini"`) or a {@link ModelSelection}. */
35
36
  model(m) {
36
37
  this.opts.model = m;
37
38
  return this;
@@ -898,6 +899,329 @@ var init_ids = __esm({
898
899
  }
899
900
  });
900
901
 
902
+ // src/internal/runtime/config/default-model.ts
903
+ var DEFAULT_AGENTIC_MODEL_ID;
904
+ var init_default_model = __esm({
905
+ "src/internal/runtime/config/default-model.ts"() {
906
+ DEFAULT_AGENTIC_MODEL_ID = "google/gemini-2.0-flash-001";
907
+ }
908
+ });
909
+ function toJsonSchema(schema, options = { unrepresentable: "any" }) {
910
+ return zod.toJSONSchema(schema, options);
911
+ }
912
+ var init_to_json_schema = __esm({
913
+ "src/internal/zod/to-json-schema.ts"() {
914
+ }
915
+ });
916
+ function requireZod() {
917
+ if (cachedZ !== void 0) return cachedZ;
918
+ const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
919
+ let mod;
920
+ try {
921
+ mod = r("zod");
922
+ } catch (cause) {
923
+ throw new ConfigurationError(
924
+ 'Structured output requires the optional peer dependency `zod`. Add `"zod": "^3.25.0 || ^4.0.0"` to your package.json and reinstall.',
925
+ { code: "zod_not_installed", cause }
926
+ );
927
+ }
928
+ cachedZ = mod.z ?? mod;
929
+ return cachedZ;
930
+ }
931
+ function makeOutputTool(jsonSchema, onCapture) {
932
+ return {
933
+ name: "output",
934
+ description: "Call this tool with your final structured answer. Match the JSON schema exactly.",
935
+ inputSchema: jsonSchema,
936
+ handler: (input) => {
937
+ const out = onCapture(input);
938
+ if (typeof out === "string") return out;
939
+ if (out instanceof Promise) return out;
940
+ return "";
941
+ }
942
+ };
943
+ }
944
+ function buildTransientAgentOptions(params) {
945
+ return {
946
+ model: params.model,
947
+ local: params.local,
948
+ tools: [params.outputTool],
949
+ systemPrompt: params.systemPrompt ?? "You produce structured output by calling the `output` tool exactly once. Match the JSON schema.",
950
+ ...params.apiKey !== void 0 ? { apiKey: params.apiKey } : {},
951
+ ...params.providers !== void 0 ? { providers: params.providers } : {}
952
+ };
953
+ }
954
+ function extractUsage(result) {
955
+ const u = result.usage;
956
+ if (u === void 0) return { inputTokens: 0, outputTokens: 0 };
957
+ return { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 };
958
+ }
959
+ function buildToolPrompt(prompt) {
960
+ return `${prompt}
961
+
962
+ Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
963
+ }
964
+ function setupStructuredOutput(schema, maxRetries) {
965
+ const z7 = requireZod();
966
+ const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
967
+ return {
968
+ z: z7,
969
+ jsonSchema,
970
+ maxRetries: maxRetries ?? 1,
971
+ initialUsage: { inputTokens: 0, outputTokens: 0 }
972
+ };
973
+ }
974
+ async function disposeAndDeleteTransient(agent, deletor) {
975
+ await agent.dispose();
976
+ try {
977
+ await deletor(agent.agentId);
978
+ } catch {
979
+ }
980
+ }
981
+ var cachedZ;
982
+ var init_structured_output_helpers = __esm({
983
+ "src/internal/structured-output-helpers.ts"() {
984
+ init_errors();
985
+ init_to_json_schema();
986
+ }
987
+ });
988
+
989
+ // src/generate-object.ts
990
+ var generate_object_exports = {};
991
+ __export(generate_object_exports, {
992
+ GenerateObjectError: () => GenerateObjectError,
993
+ generateObjectImpl: () => generateObjectImpl
994
+ });
995
+ function salvagePartial(schema, raw) {
996
+ if (typeof raw !== "object" || raw === null) return raw;
997
+ const shape = schema.shape;
998
+ if (shape === void 0 || typeof shape !== "object") return raw;
999
+ const rawObj = raw;
1000
+ const out = {};
1001
+ for (const [key, fieldSchema] of Object.entries(shape)) {
1002
+ if (typeof fieldSchema?.safeParse !== "function") continue;
1003
+ const parsed = fieldSchema.safeParse(rawObj[key]);
1004
+ if (parsed.success) out[key] = parsed.data;
1005
+ }
1006
+ return out;
1007
+ }
1008
+ async function runReasoningPhase(options, deps) {
1009
+ const reasoningOptions = {
1010
+ model: options.model,
1011
+ local: options.local,
1012
+ ...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
1013
+ ...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
1014
+ ...options.providers !== void 0 ? { providers: options.providers } : {}
1015
+ };
1016
+ const reasoningAgent = await deps.create(reasoningOptions);
1017
+ try {
1018
+ const run = await reasoningAgent.send(options.prompt);
1019
+ const result = await run.wait();
1020
+ const text = result.result;
1021
+ return typeof text === "string" ? text : options.prompt;
1022
+ } finally {
1023
+ await disposeAndDeleteTransient(reasoningAgent, deps.delete);
1024
+ }
1025
+ }
1026
+ async function generateObjectImpl(options, deps) {
1027
+ const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(
1028
+ options.schema,
1029
+ options.maxRetries
1030
+ );
1031
+ let capturedRaw;
1032
+ let lastUsage = initialUsage;
1033
+ const sentinel = /* @__PURE__ */ Symbol("generate-object-sentinel");
1034
+ class CaptureSentinel extends Error {
1035
+ constructor(captured) {
1036
+ super("generate-object-capture");
1037
+ this.captured = captured;
1038
+ }
1039
+ captured;
1040
+ [sentinel] = true;
1041
+ }
1042
+ const outputTool = makeOutputTool(jsonSchema, (input) => {
1043
+ if (capturedRaw === void 0) {
1044
+ capturedRaw = input;
1045
+ }
1046
+ throw new CaptureSentinel(input);
1047
+ });
1048
+ const reasoningText = options.structuringModel !== void 0 ? await runReasoningPhase(options, deps) : void 0;
1049
+ const structuringModel = options.structuringModel ?? options.model;
1050
+ const structuringPrompt = reasoningText ?? options.prompt;
1051
+ const agentOptions = buildTransientAgentOptions({
1052
+ model: structuringModel,
1053
+ local: options.local,
1054
+ outputTool,
1055
+ ...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
1056
+ ...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
1057
+ ...options.providers !== void 0 ? { providers: options.providers } : {}
1058
+ });
1059
+ const agent = await deps.create(agentOptions);
1060
+ try {
1061
+ const userMessage = buildToolPrompt(structuringPrompt);
1062
+ let lastParseError;
1063
+ for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
1064
+ capturedRaw = void 0;
1065
+ const run = await agent.send(userMessage);
1066
+ const result = await run.wait();
1067
+ lastUsage = extractUsage(result);
1068
+ if (capturedRaw === void 0) {
1069
+ if (result.status === "error" && result.error !== void 0) {
1070
+ throw new GenerateObjectError(
1071
+ "no_tool_call",
1072
+ `Agent run failed before the model could reply: ${result.error.message ?? "unknown error"} [${result.error.code ?? "?"}]`,
1073
+ result.error
1074
+ );
1075
+ }
1076
+ if (attempt === maxRetries) {
1077
+ throw new GenerateObjectError(
1078
+ "no_tool_call",
1079
+ "The model returned text instead of calling the `output` tool."
1080
+ );
1081
+ }
1082
+ continue;
1083
+ }
1084
+ const parsed = options.schema.safeParse(capturedRaw);
1085
+ if (parsed.success) {
1086
+ return {
1087
+ object: parsed.data,
1088
+ raw: capturedRaw,
1089
+ usage: lastUsage,
1090
+ finishReason: "tool_use"
1091
+ };
1092
+ }
1093
+ lastParseError = parsed.error;
1094
+ }
1095
+ if (options.errorStrategy === "return-raw") {
1096
+ return {
1097
+ object: capturedRaw,
1098
+ raw: capturedRaw,
1099
+ usage: lastUsage,
1100
+ finishReason: "tool_use"
1101
+ };
1102
+ }
1103
+ if (options.errorStrategy === "return-partial") {
1104
+ return {
1105
+ object: salvagePartial(options.schema, capturedRaw),
1106
+ raw: capturedRaw,
1107
+ usage: lastUsage,
1108
+ finishReason: "tool_use"
1109
+ };
1110
+ }
1111
+ throw new GenerateObjectError(
1112
+ "parse_failed",
1113
+ "Schema parse failed after all retries.",
1114
+ lastParseError
1115
+ );
1116
+ } finally {
1117
+ await disposeAndDeleteTransient(agent, deps.delete);
1118
+ }
1119
+ }
1120
+ var GenerateObjectError;
1121
+ var init_generate_object = __esm({
1122
+ "src/generate-object.ts"() {
1123
+ init_structured_output_helpers();
1124
+ GenerateObjectError = class extends Error {
1125
+ name = "GenerateObjectError";
1126
+ code;
1127
+ cause;
1128
+ constructor(code, message, cause) {
1129
+ super(message);
1130
+ this.code = code;
1131
+ if (cause !== void 0) this.cause = cause;
1132
+ }
1133
+ };
1134
+ }
1135
+ });
1136
+
1137
+ // src/internal/runtime/registry/agent-factory-registry.ts
1138
+ var agent_factory_registry_exports = {};
1139
+ __export(agent_factory_registry_exports, {
1140
+ getAgentFacade: () => getAgentFacade,
1141
+ setAgentFacade: () => setAgentFacade
1142
+ });
1143
+ function setAgentFacade(facade) {
1144
+ registered = facade;
1145
+ }
1146
+ function getAgentFacade() {
1147
+ if (registered === void 0) {
1148
+ throw new Error(
1149
+ "internal: Agent facade not registered. The `agent.ts` module must be loaded before internal subsystems (LocalAgent.runUntil/fork, eval, scorers, cron) invoke it."
1150
+ );
1151
+ }
1152
+ return registered;
1153
+ }
1154
+ var registered;
1155
+ var init_agent_factory_registry = __esm({
1156
+ "src/internal/runtime/registry/agent-factory-registry.ts"() {
1157
+ }
1158
+ });
1159
+
1160
+ // src/agent-generate.ts
1161
+ async function agentGenerate(agent, agentModel, agentApiKey, agentLocal, input, options) {
1162
+ const { output, maxRetries, errorStrategy, ...sendOptions } = options;
1163
+ const run = await agent.send(input, sendOptions);
1164
+ const result = await run.wait();
1165
+ const { generateObjectImpl: generateObjectImpl2, GenerateObjectError: GenerateObjectError2 } = await Promise.resolve().then(() => (init_generate_object(), generate_object_exports));
1166
+ const answer = structurableAnswerOrThrow(result, GenerateObjectError2);
1167
+ const { getAgentFacade: getAgentFacade2 } = await Promise.resolve().then(() => (init_agent_factory_registry(), agent_factory_registry_exports));
1168
+ const facade = getAgentFacade2();
1169
+ const structured = await generateObjectImpl2(
1170
+ {
1171
+ prompt: answer,
1172
+ schema: output,
1173
+ // `agentModel` arrives already normalized (`this.model` passed through
1174
+ // `normalizeModel` in the LocalAgent/CloudAgent constructor), so the widened
1175
+ // `string | ModelSelection` field only ever receives a `ModelSelection` here.
1176
+ model: agentModel ?? { id: DEFAULT_AGENTIC_MODEL_ID },
1177
+ // `local` is required to keep the transient structuring agent local-only;
1178
+ // default to the process cwd when the agent had no explicit local config.
1179
+ local: agentLocal ?? { cwd: process.cwd() },
1180
+ ...agentApiKey !== void 0 ? { apiKey: agentApiKey } : {},
1181
+ ...maxRetries !== void 0 ? { maxRetries } : {},
1182
+ ...errorStrategy !== void 0 ? { errorStrategy } : {}
1183
+ },
1184
+ {
1185
+ create: (opts) => facade.create(opts),
1186
+ delete: (agentId) => facade.delete(agentId)
1187
+ }
1188
+ );
1189
+ return {
1190
+ object: structured.object,
1191
+ result,
1192
+ raw: structured.raw,
1193
+ usage: structured.usage
1194
+ };
1195
+ }
1196
+ function structurableAnswerOrThrow(result, GenerateObjectError2) {
1197
+ if (result.status === "error") {
1198
+ throw new GenerateObjectError2(
1199
+ "no_tool_call",
1200
+ `Agent run failed before an answer could be structured: ${result.error?.message ?? "unknown error"} [${result.error?.code ?? "?"}]`,
1201
+ result.error
1202
+ );
1203
+ }
1204
+ if (result.status === "cancelled") {
1205
+ throw new GenerateObjectError2(
1206
+ "no_tool_call",
1207
+ "Agent run was cancelled before an answer could be structured."
1208
+ );
1209
+ }
1210
+ const answer = result.result;
1211
+ if (answer === void 0 || answer.length === 0) {
1212
+ throw new GenerateObjectError2(
1213
+ "no_tool_call",
1214
+ "The tool loop finished with no text answer (tool-only completion) \u2014 there is nothing to structure."
1215
+ );
1216
+ }
1217
+ return answer;
1218
+ }
1219
+ var init_agent_generate = __esm({
1220
+ "src/agent-generate.ts"() {
1221
+ init_default_model();
1222
+ }
1223
+ });
1224
+
901
1225
  // src/internal/persistence/cwd-mutex.ts
902
1226
  function withCwdMutex(key, fn) {
903
1227
  const prev = tails.get(key) ?? Promise.resolve();
@@ -1067,11 +1391,21 @@ var init_path_guard = __esm({
1067
1391
  }
1068
1392
  });
1069
1393
 
1070
- // src/internal/runtime/config/default-model.ts
1071
- var DEFAULT_AGENTIC_MODEL_ID;
1072
- var init_default_model = __esm({
1073
- "src/internal/runtime/config/default-model.ts"() {
1074
- DEFAULT_AGENTIC_MODEL_ID = "google/gemini-2.0-flash-001";
1394
+ // src/internal/runtime/model-selection.ts
1395
+ function normalizeModel(m) {
1396
+ if (m === void 0 || typeof m !== "string") return m;
1397
+ const id = m.trim();
1398
+ if (id.length === 0) {
1399
+ throw new ConfigurationError(
1400
+ 'model must be a non-empty "provider/model" id string or a ModelSelection object',
1401
+ { code: "invalid_model_selection" }
1402
+ );
1403
+ }
1404
+ return { id };
1405
+ }
1406
+ var init_model_selection = __esm({
1407
+ "src/internal/runtime/model-selection.ts"() {
1408
+ init_errors();
1075
1409
  }
1076
1410
  });
1077
1411
  function detectNetworkFsName(typeMagic) {
@@ -1211,7 +1545,10 @@ var init_enabled_names = __esm({
1211
1545
  function stripSecretsFromOptions(options) {
1212
1546
  return assignDefined({
1213
1547
  name: options.name,
1214
- model: options.model !== void 0 ? { id: options.model.id } : void 0,
1548
+ model: (() => {
1549
+ const m = normalizeModel(options.model);
1550
+ return m !== void 0 ? { id: m.id } : void 0;
1551
+ })(),
1215
1552
  systemPrompt: typeof options.systemPrompt === "string" ? options.systemPrompt : void 0,
1216
1553
  local: serializeLocal(options.local),
1217
1554
  cloud: serializeCloud(options.cloud),
@@ -1382,6 +1719,7 @@ var init_agent_registry_store = __esm({
1382
1719
  init_cwd_mutex();
1383
1720
  init_schema_version();
1384
1721
  init_enabled_names();
1722
+ init_model_selection();
1385
1723
  SCHEMA_VERSION = 1;
1386
1724
  LEGACY_SCHEMA_VERSION_STRING = "1.0";
1387
1725
  REGISTRY_RELATIVE_PATH = path.join(".theokit", "agents", "registry.json");
@@ -1517,7 +1855,8 @@ function serializeCloudAgentConfig(options) {
1517
1855
  cloud: serializeCloud2(options.cloud)
1518
1856
  };
1519
1857
  if (typeof options.agentId === "string") payload.agentId = options.agentId;
1520
- if (options.model !== void 0) payload.model = { id: options.model.id };
1858
+ const cfgModel = normalizeModel(options.model);
1859
+ if (cfgModel !== void 0) payload.model = { id: cfgModel.id };
1521
1860
  if (typeof options.systemPrompt === "string") payload.systemPrompt = options.systemPrompt;
1522
1861
  const skills = serializeSkills(options.skills);
1523
1862
  if (skills !== void 0) payload.skills = skills;
@@ -1627,6 +1966,7 @@ function serializeMemory2(memory) {
1627
1966
  var init_cloud_config_serializer = __esm({
1628
1967
  "src/internal/runtime/cloud/cloud-config-serializer.ts"() {
1629
1968
  init_enabled_names();
1969
+ init_model_selection();
1630
1970
  }
1631
1971
  });
1632
1972
 
@@ -2337,6 +2677,7 @@ function applyScriptMetrics(base, script) {
2337
2677
  if (script.cost !== void 0) base.cost = script.cost;
2338
2678
  if (script.stoppedAtIterationLimit === true) base.stoppedAtIterationLimit = true;
2339
2679
  if (script.stoppedByDoomLoop === true) base.stoppedByDoomLoop = true;
2680
+ if (script.origin !== void 0) base.origin = script.origin;
2340
2681
  }
2341
2682
  var FixtureRunBase;
2342
2683
  var init_fixture_run_base = __esm({
@@ -2844,6 +3185,7 @@ function buildFixtureArtifacts() {
2844
3185
  var CloudAgent;
2845
3186
  var init_cloud_agent = __esm({
2846
3187
  "src/internal/runtime/cloud/cloud-agent.ts"() {
3188
+ init_agent_generate();
2847
3189
  init_errors();
2848
3190
  init_env();
2849
3191
  init_fixture_mode();
@@ -2851,6 +3193,7 @@ var init_cloud_agent = __esm({
2851
3193
  init_cwd_mutex();
2852
3194
  init_path_guard();
2853
3195
  init_default_model();
3196
+ init_model_selection();
2854
3197
  init_agent_registry();
2855
3198
  init_system_prompt();
2856
3199
  init_cloud_config_serializer();
@@ -2870,7 +3213,7 @@ var init_cloud_agent = __esm({
2870
3213
  disposed = false;
2871
3214
  constructor(options, providedAgentId) {
2872
3215
  this.agentId = providedAgentId ?? options.agentId ?? generateCloudAgentId();
2873
- this.model = options.model;
3216
+ this.model = normalizeModel(options.model);
2874
3217
  this.options = options;
2875
3218
  this.cloudPayload = serializeCloudAgentConfig({ ...options, agentId: this.agentId });
2876
3219
  const repoUrls = (options.cloud?.repos ?? []).map((repo) => repo.url);
@@ -2900,6 +3243,17 @@ var init_cloud_agent = __esm({
2900
3243
  const apiKey = resolveApiKey(this.options.apiKey);
2901
3244
  return isFixtureApiKey(apiKey) && getConfiguredBaseUrl() === void 0;
2902
3245
  }
3246
+ // SE9 — integrated structured output; delegates to the shared helper.
3247
+ generate(message, options) {
3248
+ return agentGenerate(
3249
+ this,
3250
+ this.model,
3251
+ this.options.apiKey,
3252
+ this.options.local,
3253
+ message,
3254
+ options
3255
+ );
3256
+ }
2903
3257
  async send(message, options = {}) {
2904
3258
  if (options.tools !== void 0 && options.tools.length > 0) {
2905
3259
  throw new ConfigurationError(
@@ -2930,7 +3284,7 @@ var init_cloud_agent = __esm({
2930
3284
  });
2931
3285
  }
2932
3286
  async sendLocked(message, options) {
2933
- const overrideModel = options.model;
3287
+ const overrideModel = normalizeModel(options.model);
2934
3288
  if (overrideModel !== void 0) {
2935
3289
  this.model = overrideModel;
2936
3290
  updateRegisteredAgent(this.agentId, { model: overrideModel });
@@ -4124,12 +4478,12 @@ function tryAutoRegisterAdapters(settings) {
4124
4478
  if (settings.autoDetect === false) return;
4125
4479
  const disabled = new Set(settings.disable ?? []);
4126
4480
  for (const adapter of ALL_ADAPTERS) {
4127
- if (registered.has(adapter.moduleName)) continue;
4481
+ if (registered2.has(adapter.moduleName)) continue;
4128
4482
  if (disabled.has(adapter.displayName.toLowerCase())) continue;
4129
4483
  if (!adapter.detect()) continue;
4130
4484
  try {
4131
4485
  adapter.register();
4132
- registered.add(adapter.moduleName);
4486
+ registered2.add(adapter.moduleName);
4133
4487
  process.stderr.write(`[theokit-sdk] telemetry: ${adapter.displayName} auto-instrumented.
4134
4488
  `);
4135
4489
  } catch (cause) {
@@ -4141,7 +4495,7 @@ function tryAutoRegisterAdapters(settings) {
4141
4495
  }
4142
4496
  }
4143
4497
  }
4144
- var ALL_ADAPTERS, registered;
4498
+ var ALL_ADAPTERS, registered2;
4145
4499
  var init_adapter_registry = __esm({
4146
4500
  "src/internal/telemetry/adapter-registry.ts"() {
4147
4501
  init_arize();
@@ -4160,7 +4514,7 @@ var init_adapter_registry = __esm({
4160
4514
  arizeAdapter,
4161
4515
  braintrustAdapter
4162
4516
  ];
4163
- registered = /* @__PURE__ */ new Set();
4517
+ registered2 = /* @__PURE__ */ new Set();
4164
4518
  }
4165
4519
  });
4166
4520
  function loadOtel() {
@@ -4751,6 +5105,30 @@ var init_pagination = __esm({
4751
5105
  "src/internal/persistence/pagination.ts"() {
4752
5106
  }
4753
5107
  });
5108
+
5109
+ // src/internal/persistence/session-meta.ts
5110
+ function applyMetaPatch(current, patch) {
5111
+ const next = {};
5112
+ if (current.title !== void 0) next.title = current.title;
5113
+ if (current.tag !== void 0) next.tag = current.tag;
5114
+ if (patch.title === null) delete next.title;
5115
+ else if (patch.title !== void 0) next.title = patch.title;
5116
+ if (patch.tag === null) delete next.tag;
5117
+ else if (patch.tag !== void 0) next.tag = patch.tag;
5118
+ return next;
5119
+ }
5120
+ function coerceSessionMeta(raw) {
5121
+ if (typeof raw !== "object" || raw === null) return void 0;
5122
+ const obj = raw;
5123
+ const meta = {};
5124
+ if (typeof obj.title === "string") meta.title = obj.title;
5125
+ if (typeof obj.tag === "string") meta.tag = obj.tag;
5126
+ return meta.title === void 0 && meta.tag === void 0 ? void 0 : meta;
5127
+ }
5128
+ var init_session_meta = __esm({
5129
+ "src/internal/persistence/session-meta.ts"() {
5130
+ }
5131
+ });
4754
5132
  function toStoredMessage(record) {
4755
5133
  return {
4756
5134
  role: record.role,
@@ -4766,7 +5144,9 @@ var init_conversation_storage_fs = __esm({
4766
5144
  "src/internal/persistence/conversation-storage-fs.ts"() {
4767
5145
  init_agent_session_store();
4768
5146
  init_security();
5147
+ init_file_lock();
4769
5148
  init_pagination();
5149
+ init_session_meta();
4770
5150
  FileSystemConversationStorage = class {
4771
5151
  #root;
4772
5152
  constructor(opts = {}) {
@@ -4816,6 +5196,37 @@ var init_conversation_storage_fs = __esm({
4816
5196
  async compact(conversationId, maxTurns) {
4817
5197
  await compactSessionFile(this.#root, conversationId, maxTurns);
4818
5198
  }
5199
+ // SE4 — session metadata persisted as a per-conversation sidecar
5200
+ // `<root>/.theokit/agents/<safeId>/session.json` (same sanitized perimeter as
5201
+ // the transcript). Kept separate from messages.jsonl so a title/tag write does
5202
+ // not rewrite the append-only log.
5203
+ #metaPath(conversationId) {
5204
+ const safe2 = sanitizeIdentifier(conversationId, { maxLen: 128 });
5205
+ return safePathJoin(this.#root, ".theokit", "agents", safe2, "session.json");
5206
+ }
5207
+ async getSessionMeta(conversationId) {
5208
+ try {
5209
+ const raw = await promises.readFile(this.#metaPath(conversationId), "utf8");
5210
+ return coerceSessionMeta(JSON.parse(raw));
5211
+ } catch (cause) {
5212
+ if (cause.code === "ENOENT") return void 0;
5213
+ throw cause;
5214
+ }
5215
+ }
5216
+ async setSessionMeta(conversationId, patch) {
5217
+ const metaPath = this.#metaPath(conversationId);
5218
+ await promises.mkdir(path.dirname(metaPath), { recursive: true });
5219
+ await withFileLock(metaPath, async () => {
5220
+ let current = {};
5221
+ try {
5222
+ current = coerceSessionMeta(JSON.parse(await promises.readFile(metaPath, "utf8"))) ?? {};
5223
+ } catch (cause) {
5224
+ if (cause.code !== "ENOENT") throw cause;
5225
+ }
5226
+ const next = applyMetaPatch(current, patch);
5227
+ await promises.writeFile(metaPath, redactSecrets(JSON.stringify(next)), "utf8");
5228
+ });
5229
+ }
4819
5230
  async dispose() {
4820
5231
  }
4821
5232
  };
@@ -6879,7 +7290,7 @@ function bootstrapSubmanagers(args) {
6879
7290
  const providerCount = (args.options.providers?.routes?.length ?? 0) + enabledPluginNames(args.options.plugins).length;
6880
7291
  if (providerCount > 0 || args.options.providers !== void 0) {
6881
7292
  out.providers = new ProvidersManagerImpl(
6882
- args.options.model,
7293
+ normalizeModel(args.options.model),
6883
7294
  args.options.providers,
6884
7295
  args.options.plugins
6885
7296
  );
@@ -6916,6 +7327,7 @@ var init_local_agent_bootstrap = __esm({
6916
7327
  init_enabled_names();
6917
7328
  init_providers_manager();
6918
7329
  init_context_manager();
7330
+ init_model_selection();
6919
7331
  init_plugins_manager();
6920
7332
  init_agent_registry();
6921
7333
  init_skills_manager();
@@ -6964,6 +7376,7 @@ function createLocalRun(options) {
6964
7376
  projectMcpServers: options.projectMcpServers,
6965
7377
  ...options.persistMemoryFact !== void 0 ? { persistMemoryFact: options.persistMemoryFact } : {}
6966
7378
  });
7379
+ if (options.sendOptions.origin !== void 0) script.origin = options.sendOptions.origin;
6967
7380
  const handle = new LocalRun({
6968
7381
  id,
6969
7382
  agentId: options.agentId,
@@ -7664,6 +8077,19 @@ var init_loop_llm_stream = __esm({
7664
8077
  init_message_builders();
7665
8078
  }
7666
8079
  });
8080
+
8081
+ // src/types/run-events.ts
8082
+ function emitRunEvent(sink, event) {
8083
+ if (sink === void 0) return;
8084
+ try {
8085
+ sink(event);
8086
+ } catch {
8087
+ }
8088
+ }
8089
+ var init_run_events = __esm({
8090
+ "src/types/run-events.ts"() {
8091
+ }
8092
+ });
7667
8093
  async function withToolWhitelist(whitelist, fn) {
7668
8094
  return toolWhitelistStore.run(whitelist, fn);
7669
8095
  }
@@ -7835,6 +8261,27 @@ var init_repair_middleware = __esm({
7835
8261
  }
7836
8262
  });
7837
8263
 
8264
+ // src/tool-error.ts
8265
+ function renderToolErrorMessage(content) {
8266
+ if (typeof content === "string") return content;
8267
+ return content.map((block) => block.type === "text" ? block.text : `[${block.source.media_type} image]`).join("\n");
8268
+ }
8269
+ var ToolError;
8270
+ var init_tool_error = __esm({
8271
+ "src/tool-error.ts"() {
8272
+ init_errors();
8273
+ ToolError = class extends TheokitAgentError {
8274
+ name = "ToolError";
8275
+ /** The error content surfaced to the model: a string, or text/image blocks. */
8276
+ content;
8277
+ constructor(content, options = {}) {
8278
+ super(renderToolErrorMessage(content), { ...options, isRetryable: false });
8279
+ this.content = content;
8280
+ }
8281
+ };
8282
+ }
8283
+ });
8284
+
7838
8285
  // src/internal/runtime/tools/shell-tool.ts
7839
8286
  async function runShell(options) {
7840
8287
  if (options.sandbox === true && isObviouslyUnsafe(options.command)) {
@@ -7879,23 +8326,27 @@ async function executeTool(inputs, resolved, call) {
7879
8326
  if (resolved.origin === "shell") return runShellTool(inputs, call);
7880
8327
  if (resolved.origin === "memory") return runMemoryTool(resolved, call, inputs.context);
7881
8328
  if (resolved.origin === "custom")
7882
- return runCustomTool(resolved, call, inputs.signal, inputs.context);
8329
+ return runCustomTool(resolved, call, inputs.signal, inputs.context, inputs.messages);
7883
8330
  return runMcpTool(inputs, resolved, call);
7884
8331
  }
7885
8332
  async function runMemoryTool(resolved, call, context) {
7886
8333
  return runHandlerTool("memory", resolved.memoryHandler, call, void 0, context);
7887
8334
  }
7888
- async function runCustomTool(resolved, call, signal, context) {
7889
- return runHandlerTool("custom", resolved.customHandler, call, signal, context);
8335
+ async function runCustomTool(resolved, call, signal, context, messages) {
8336
+ return runHandlerTool("custom", resolved.customHandler, call, signal, context, messages);
7890
8337
  }
7891
- async function runHandlerTool(kind, handler, call, signal, context) {
8338
+ async function runHandlerTool(kind, handler, call, signal, context, messages) {
7892
8339
  if (handler === void 0) {
7893
8340
  return { stdout: "", stderr: `${kind} tool ${call.name} has no handler`, exitCode: 127 };
7894
8341
  }
7895
8342
  try {
7896
- const stdout = await handler(call.input, { signal, context });
7897
- return { stdout, stderr: "", exitCode: 0 };
8343
+ const out = await handler(call.input, { signal, context, messages });
8344
+ if (typeof out !== "string") return { stdout: "", stderr: "", exitCode: 0, content: out };
8345
+ return { stdout: out, stderr: "", exitCode: 0 };
7898
8346
  } catch (cause) {
8347
+ if (cause instanceof ToolError) {
8348
+ return { stdout: "", stderr: cause.message, exitCode: 1, content: cause.content };
8349
+ }
7899
8350
  const message = cause instanceof Error ? cause.message : String(cause);
7900
8351
  return { stdout: "", stderr: message, exitCode: 1 };
7901
8352
  }
@@ -7940,6 +8391,7 @@ ${result.stderr}`.trim();
7940
8391
  }
7941
8392
  var init_tool_executors = __esm({
7942
8393
  "src/internal/agent-loop/tool-executors.ts"() {
8394
+ init_tool_error();
7943
8395
  init_shell_tool();
7944
8396
  }
7945
8397
  });
@@ -8024,6 +8476,11 @@ async function dispatchSingleCall(inputs, tools, call, events, parentSpan) {
8024
8476
  toolSpan?.end();
8025
8477
  return fileVeto;
8026
8478
  }
8479
+ emitRunEvent(inputs.runEventSink, {
8480
+ type: "tool_progress",
8481
+ toolName: workingCall.name,
8482
+ toolCallId: callId
8483
+ });
8027
8484
  const result = await runToolWithLifecycle(inputs, resolved, workingCall, callId);
8028
8485
  await inputs.pluginManager?.runPostToolCallHooks({
8029
8486
  name: workingCall.name,
@@ -8050,6 +8507,13 @@ function applyRepairAndExtractCall(tools, call) {
8050
8507
  function vetoFromForkWhitelist(inputs, call, callId, events) {
8051
8508
  const whitelistDecision = checkToolWhitelist(call.name);
8052
8509
  if (whitelistDecision.allowed) return void 0;
8510
+ emitRunEvent(inputs.runEventSink, {
8511
+ type: "permission_denied",
8512
+ toolName: call.name,
8513
+ toolCallId: callId,
8514
+ source: "fork_whitelist",
8515
+ message: whitelistDecision.reason ?? "tool not available in fork"
8516
+ });
8053
8517
  events.push(buildToolUseRunning(inputs, callId, call));
8054
8518
  events.push(
8055
8519
  buildToolUseCompleted(inputs, callId, call, {
@@ -8086,6 +8550,13 @@ async function vetoFromPluginPreHook(inputs, call, callId, events) {
8086
8550
  runId: inputs.runId
8087
8551
  });
8088
8552
  if (pluginVeto === void 0) return void 0;
8553
+ emitRunEvent(inputs.runEventSink, {
8554
+ type: "permission_denied",
8555
+ toolName: call.name,
8556
+ toolCallId: callId,
8557
+ source: "plugin",
8558
+ message: pluginVeto.message
8559
+ });
8089
8560
  events.push(
8090
8561
  buildToolUseCompleted(inputs, callId, call, {
8091
8562
  stdout: "",
@@ -8108,6 +8579,13 @@ async function vetoFromFileHookPreDecision(inputs, call, callId, events) {
8108
8579
  runId: inputs.runId
8109
8580
  });
8110
8581
  if (!preDecision.blocked) return void 0;
8582
+ emitRunEvent(inputs.runEventSink, {
8583
+ type: "permission_denied",
8584
+ toolName: call.name,
8585
+ toolCallId: callId,
8586
+ source: "file_hook",
8587
+ message: preDecision.reason ?? "blocked by hook"
8588
+ });
8111
8589
  events.push(
8112
8590
  buildToolUseCompleted(inputs, callId, call, {
8113
8591
  stdout: "",
@@ -8151,7 +8629,9 @@ async function runToolWithLifecycle(inputs, resolved, call, callId) {
8151
8629
  await safeEmitToolHook(inputs.onToolEnd, {
8152
8630
  toolName: call.name,
8153
8631
  args: call.input,
8154
- result: result.stdout,
8632
+ // SE7 — a block-returning handler has empty `stdout`; surface its structured
8633
+ // content to the hook instead of an empty string.
8634
+ result: result.content !== void 0 ? result.content : result.stdout,
8155
8635
  conversationId: inputs.agentId,
8156
8636
  callId,
8157
8637
  durationMs
@@ -8173,7 +8653,10 @@ function finalizeSpanAndPostHook(inputs, call, callId, result, events, toolSpan)
8173
8653
  output: {
8174
8654
  stdout: result.stdout,
8175
8655
  stderr: result.stderr,
8176
- exitCode: result.exitCode ?? 0
8656
+ exitCode: result.exitCode ?? 0,
8657
+ // SE7 — structured content (text + image blocks) when the handler
8658
+ // returned/threw blocks; absent for the string path.
8659
+ ...result.content !== void 0 ? { content: result.content } : {}
8177
8660
  },
8178
8661
  agentId: inputs.agentId,
8179
8662
  runId: inputs.runId
@@ -8186,7 +8669,9 @@ function finalizeSpanAndPostHook(inputs, call, callId, result, events, toolSpan)
8186
8669
  return {
8187
8670
  type: "tool_result",
8188
8671
  toolUseId: call.id,
8189
- content: renderToolResult(result),
8672
+ // SE7 — structured content blocks (handler-returned or ToolError-carried)
8673
+ // are authoritative; otherwise the legacy string rendering.
8674
+ content: result.content !== void 0 ? result.content : renderToolResult(result),
8190
8675
  ...result.exitCode !== 0 && result.exitCode !== void 0 ? { isError: true } : {}
8191
8676
  };
8192
8677
  }
@@ -8236,6 +8721,7 @@ function buildToolUseCompleted(inputs, callId, call, result) {
8236
8721
  }
8237
8722
  var init_tool_dispatch = __esm({
8238
8723
  "src/internal/agent-loop/tool-dispatch.ts"() {
8724
+ init_run_events();
8239
8725
  init_ids();
8240
8726
  init_async_local_storage();
8241
8727
  init_map_with_concurrency();
@@ -8246,6 +8732,33 @@ var init_tool_dispatch = __esm({
8246
8732
  }
8247
8733
  });
8248
8734
 
8735
+ // src/internal/llm/tool-result-content.ts
8736
+ function toBlockToolResultContent(content) {
8737
+ return content;
8738
+ }
8739
+ function toStringToolResultContent(content, providerName) {
8740
+ if (typeof content === "string") return content;
8741
+ if (content.some((block) => block.type === "image")) {
8742
+ throw new ConfigurationError(
8743
+ `provider "${providerName}" does not support image content in tool results`
8744
+ );
8745
+ }
8746
+ return content.filter(
8747
+ (block) => block.type === "text"
8748
+ ).map((block) => block.text).join("\n");
8749
+ }
8750
+ function renderToolResultContentText(content, fn) {
8751
+ if (typeof content === "string") return fn(content);
8752
+ return content.map(
8753
+ (block) => block.type === "text" ? { type: "text", text: fn(block.text) } : block
8754
+ );
8755
+ }
8756
+ var init_tool_result_content = __esm({
8757
+ "src/internal/llm/tool-result-content.ts"() {
8758
+ init_errors();
8759
+ }
8760
+ });
8761
+
8249
8762
  // src/internal/agent-loop/tool-result-guard.ts
8250
8763
  function guardText(content, opts) {
8251
8764
  let out = content;
@@ -8263,12 +8776,17 @@ ${CLOSE}`;
8263
8776
  function applyToolResultGuard(parts, opts) {
8264
8777
  if (opts.delimit !== true && opts.redactPii !== true) return parts;
8265
8778
  return parts.map(
8266
- (p) => p.type === "tool_result" ? { ...p, content: guardText(p.content, opts) } : p
8779
+ (p) => (
8780
+ // SE7 — guard the TEXT of a tool result (string or the text blocks of a
8781
+ // structured content); image blocks pass through untouched.
8782
+ p.type === "tool_result" ? { ...p, content: renderToolResultContentText(p.content, (t) => guardText(t, opts)) } : p
8783
+ )
8267
8784
  );
8268
8785
  }
8269
8786
  var OPEN, CLOSE, PII_PATTERNS;
8270
8787
  var init_tool_result_guard = __esm({
8271
8788
  "src/internal/agent-loop/tool-result-guard.ts"() {
8789
+ init_tool_result_content();
8272
8790
  OPEN = "<untrusted-tool-output>";
8273
8791
  CLOSE = "</untrusted-tool-output>";
8274
8792
  PII_PATTERNS = [
@@ -8647,6 +9165,14 @@ var init_usage_and_cost = __esm({
8647
9165
  });
8648
9166
 
8649
9167
  // src/internal/agent-loop/loop.ts
9168
+ function projectToolContextMessages(messages) {
9169
+ const projected = [];
9170
+ for (const m of messages) {
9171
+ const content = m.content.flatMap((p) => p.type === "text" ? [p.text] : []).join("");
9172
+ if (content !== "") projected.push({ role: m.role, content });
9173
+ }
9174
+ return projected;
9175
+ }
8650
9176
  async function runAgentLoop(inputs) {
8651
9177
  const sendSpan = inputs.telemetry?.startSpan("agent.send", {
8652
9178
  agentId: inputs.agentId,
@@ -8887,7 +9413,9 @@ async function continueOrTerminate(inputs, ctx, llmOutput) {
8887
9413
  const outText = await transformLlmOutputText(inputs, llmOutput.text, tCtx);
8888
9414
  ctx.messages.push(buildAssistantTurn(outText, llmOutput.toolCalls));
8889
9415
  const rawResults = await dispatchTools(
8890
- inputs,
9416
+ // SE12 — forward a read-only text projection of the transcript-so-far to tool
9417
+ // handlers via `ctx.messages` (consumed by defineSubAgent's messageFilter).
9418
+ { ...inputs, messages: projectToolContextMessages(ctx.messages) },
8891
9419
  ctx.tools,
8892
9420
  llmOutput.toolCalls,
8893
9421
  ctx.events,
@@ -9301,8 +9829,8 @@ var init_vertex = __esm({
9301
9829
 
9302
9830
  // src/internal/providers/builtin/index.ts
9303
9831
  function registerBuiltins() {
9304
- if (registered2) return;
9305
- registered2 = true;
9832
+ if (registered3) return;
9833
+ registered3 = true;
9306
9834
  registerProvider(ANTHROPIC);
9307
9835
  registerProvider(OPENAI);
9308
9836
  registerProvider(OPENROUTER);
@@ -9314,7 +9842,7 @@ function registerBuiltins() {
9314
9842
  registerProvider(VERTEX);
9315
9843
  registerCatalogProviders();
9316
9844
  }
9317
- var registered2;
9845
+ var registered3;
9318
9846
  var init_builtin = __esm({
9319
9847
  "src/internal/providers/builtin/index.ts"() {
9320
9848
  init_catalog_loader();
@@ -9328,7 +9856,7 @@ var init_builtin = __esm({
9328
9856
  init_openai();
9329
9857
  init_openrouter();
9330
9858
  init_vertex();
9331
- registered2 = false;
9859
+ registered3 = false;
9332
9860
  }
9333
9861
  });
9334
9862
 
@@ -9573,7 +10101,9 @@ function toAnthropicWireMessage(message) {
9573
10101
  return {
9574
10102
  type: "tool_result",
9575
10103
  tool_use_id: part.toolUseId,
9576
- content: part.content,
10104
+ // SE7 — this wire is block-capable: strings pass through, structured
10105
+ // text/image blocks are forwarded natively.
10106
+ content: toBlockToolResultContent(part.content),
9577
10107
  ...part.isError === true ? { is_error: true } : {}
9578
10108
  };
9579
10109
  });
@@ -9650,6 +10180,7 @@ function encodeAnthropicSystem(system) {
9650
10180
  var init_anthropic_shared = __esm({
9651
10181
  "src/internal/llm/anthropic-shared.ts"() {
9652
10182
  init_finish();
10183
+ init_tool_result_content();
9653
10184
  }
9654
10185
  });
9655
10186
 
@@ -10604,7 +11135,8 @@ function toOllamaMessages(message) {
10604
11135
  if (part.type === "tool_result") {
10605
11136
  out.push({
10606
11137
  role: "tool",
10607
- content: part.content,
11138
+ // SE7 — string-only tool role: text blocks flatten; image fails fast.
11139
+ content: toStringToolResultContent(part.content, "ollama"),
10608
11140
  tool_name: part.toolUseId
10609
11141
  });
10610
11142
  }
@@ -10645,6 +11177,7 @@ var init_ollama_native = __esm({
10645
11177
  "src/internal/llm/ollama-native.ts"() {
10646
11178
  init_ollama2();
10647
11179
  init_finish();
11180
+ init_tool_result_content();
10648
11181
  OllamaNativeClient = class {
10649
11182
  constructor(options) {
10650
11183
  this.options = options;
@@ -11009,7 +11542,9 @@ function userOrToolMessages(message) {
11009
11542
  out.push({
11010
11543
  role: "tool",
11011
11544
  tool_call_id: part.toolUseId,
11012
- content: part.content
11545
+ // SE7 — this wire's tool role is string-only: text blocks flatten; an
11546
+ // image block fails fast (ConfigurationError).
11547
+ content: toStringToolResultContent(part.content, "openai")
11013
11548
  });
11014
11549
  }
11015
11550
  }
@@ -11040,6 +11575,7 @@ var init_openai2 = __esm({
11040
11575
  init_finish();
11041
11576
  init_hermes_tool_extract();
11042
11577
  init_sse();
11578
+ init_tool_result_content();
11043
11579
  OpenAIClient = class {
11044
11580
  constructor(options) {
11045
11581
  this.options = options;
@@ -12279,18 +12815,20 @@ var init_personality_filter = __esm({
12279
12815
  function createRealLocalRun(options) {
12280
12816
  const { userText, id, startTime } = prepareRunContext(options.message);
12281
12817
  const supported = /* @__PURE__ */ new Set(["stream", "wait", "cancel", "conversation"]);
12282
- const unusedFixtureScript = {
12818
+ const runScript = {
12283
12819
  events: [],
12284
12820
  finalStatus: "running",
12285
12821
  cancellable: false,
12286
- conversation: []
12822
+ conversation: [],
12823
+ // SE3 — carry the turn's provenance so buildResult forwards it onto RunResult.origin.
12824
+ ...options.sendOptions.origin !== void 0 ? { origin: options.sendOptions.origin } : {}
12287
12825
  };
12288
12826
  const handle = new RealLocalRun(
12289
12827
  {
12290
12828
  id,
12291
12829
  agentId: options.agentId,
12292
12830
  model: options.model,
12293
- script: unusedFixtureScript,
12831
+ script: runScript,
12294
12832
  supportedOps: supported,
12295
12833
  startTime
12296
12834
  },
@@ -12401,6 +12939,8 @@ function buildLoopInputs(options, runId, userText) {
12401
12939
  // M7 — forward SendOptions.context to the loop so every tool handler receives
12402
12940
  // it on `ctx.context` (shared run config set once, e.g. projectRoot).
12403
12941
  ...options.sendOptions.context !== void 0 ? { context: options.sendOptions.context } : {},
12942
+ // SE2 — forward the opt-in typed runtime-event sink to the loop.
12943
+ ...options.sendOptions.onRunEvent !== void 0 ? { runEventSink: options.sendOptions.onRunEvent } : {},
12404
12944
  // #58 / #57 — forward the per-tool timeout + tool-result guard so a consumer
12405
12945
  // can enable them via SendOptions (not only internal AgentLoopInputs).
12406
12946
  ...options.sendOptions.perToolTimeoutMs !== void 0 ? { perToolTimeoutMs: options.sendOptions.perToolTimeoutMs } : {},
@@ -15461,39 +16001,16 @@ Goal: ${ctx.goal}
15461
16001
  Subgoals: ${subgoals}
15462
16002
  Last agent response: ${ctx.lastResponse}
15463
16003
 
15464
- Respond with EXACTLY one of:
15465
- - DONE: <reason>
15466
- - CONTINUE: <what's left>
15467
- - SKIPPED: <why not applicable>
15468
-
15469
- Be strict. If unclear, prefer CONTINUE.`;
15470
- }
15471
- var init_judge_call = __esm({
15472
- "src/internal/judge/judge-call.ts"() {
15473
- init_parse_verdict();
15474
- }
15475
- });
15476
-
15477
- // src/internal/runtime/registry/agent-factory-registry.ts
15478
- var agent_factory_registry_exports = {};
15479
- __export(agent_factory_registry_exports, {
15480
- getAgentFacade: () => getAgentFacade,
15481
- setAgentFacade: () => setAgentFacade
15482
- });
15483
- function setAgentFacade(facade) {
15484
- registered3 = facade;
15485
- }
15486
- function getAgentFacade() {
15487
- if (registered3 === void 0) {
15488
- throw new Error(
15489
- "internal: Agent facade not registered. The `agent.ts` module must be loaded before internal subsystems (LocalAgent.runUntil/fork, eval, scorers, cron) invoke it."
15490
- );
15491
- }
15492
- return registered3;
16004
+ Respond with EXACTLY one of:
16005
+ - DONE: <reason>
16006
+ - CONTINUE: <what's left>
16007
+ - SKIPPED: <why not applicable>
16008
+
16009
+ Be strict. If unclear, prefer CONTINUE.`;
15493
16010
  }
15494
- var registered3;
15495
- var init_agent_factory_registry = __esm({
15496
- "src/internal/runtime/registry/agent-factory-registry.ts"() {
16011
+ var init_judge_call = __esm({
16012
+ "src/internal/judge/judge-call.ts"() {
16013
+ init_parse_verdict();
15497
16014
  }
15498
16015
  });
15499
16016
 
@@ -15661,14 +16178,14 @@ async function forkAgentImpl(parent, options, deps) {
15661
16178
  return {
15662
16179
  result: result.result,
15663
16180
  toolCalls: [],
15664
- usage: extractUsage(result)
16181
+ usage: extractUsage2(result)
15665
16182
  };
15666
16183
  });
15667
16184
  } finally {
15668
16185
  await fork.dispose();
15669
16186
  }
15670
16187
  }
15671
- function extractUsage(result) {
16188
+ function extractUsage2(result) {
15672
16189
  if (typeof result !== "object" || result === null) {
15673
16190
  return { inputTokens: 0, outputTokens: 0 };
15674
16191
  }
@@ -15827,7 +16344,7 @@ var init_local_agent_memory_hooks = __esm({
15827
16344
  async function executeSendLocked(inputs, message, options) {
15828
16345
  if (inputs.disposed) throw new AgentDisposedError(inputs.agentId);
15829
16346
  await consumePending(inputs.agentId, inputs.invalidationPending, inputs.clearInvalidation, inputs.reload);
15830
- inputs.applyModelOverride(options.model);
16347
+ inputs.applyModelOverride(normalizeModel(options.model));
15831
16348
  const userText = typeof message === "string" ? message : message.text;
15832
16349
  if (inputs.options.onBeforeSend !== void 0) {
15833
16350
  await inputs.options.onBeforeSend({
@@ -15896,6 +16413,7 @@ var init_local_agent_send = __esm({
15896
16413
  init_abort_utils();
15897
16414
  init_memory_path_selector();
15898
16415
  init_memory_store();
16416
+ init_model_selection();
15899
16417
  init_agent_session();
15900
16418
  init_safe_call();
15901
16419
  init_local_agent_invalidate();
@@ -16475,6 +16993,7 @@ function includesSetting(options, source) {
16475
16993
  var LocalAgent;
16476
16994
  var init_local_agent = __esm({
16477
16995
  "src/internal/runtime/local-agent/local-agent.ts"() {
16996
+ init_agent_generate();
16478
16997
  init_errors();
16479
16998
  init_ids();
16480
16999
  init_cwd_mutex();
@@ -16485,6 +17004,7 @@ var init_local_agent = __esm({
16485
17004
  init_hooks_executor();
16486
17005
  init_post_run_lifecycle();
16487
17006
  init_memory_path_selector();
17007
+ init_model_selection();
16488
17008
  init_agent_registry();
16489
17009
  init_live_agent_registry();
16490
17010
  init_agent_session();
@@ -16561,7 +17081,7 @@ var init_local_agent = __esm({
16561
17081
  constructor(options) {
16562
17082
  this.agentId = options.agentId ?? generateLocalAgentId();
16563
17083
  this._telemetry = createTelemetry(options.telemetry);
16564
- this.model = options.model;
17084
+ this.model = normalizeModel(options.model);
16565
17085
  this.options = options;
16566
17086
  this.workspaceCwd = resolveCwd(options.local?.cwd);
16567
17087
  this.conversationStorage = options.conversationStorage;
@@ -16628,6 +17148,11 @@ var init_local_agent = __esm({
16628
17148
  hooks() {
16629
17149
  return this.hooksExecutor;
16630
17150
  }
17151
+ // SE9 — integrated structured output; delegates to the shared helper.
17152
+ generate(message, options) {
17153
+ const { apiKey, local } = this.options;
17154
+ return agentGenerate(this, this.model, apiKey, local, message, options);
17155
+ }
16631
17156
  async send(message, options = {}) {
16632
17157
  if (options.tools !== void 0 && options.tools.length > 0) {
16633
17158
  validateToolCatalog(options.tools);
@@ -16860,6 +17385,7 @@ var init_local_agent = __esm({
16860
17385
  }
16861
17386
  });
16862
17387
  async function runCreateUnderSpan(options, span) {
17388
+ options = { ...options, model: normalizeModel(options.model) };
16863
17389
  validateAgentOptions(options);
16864
17390
  validateCloudToolParity(options);
16865
17391
  await guardAgainstIdCollision(options);
@@ -16933,7 +17459,10 @@ async function createLocalAgent(options) {
16933
17459
  const willFlowToProvider = !isFixtureApiKey(apiKey) && !shouldUseRealLocalRuntime(apiKey);
16934
17460
  const shape = validateApiKeyShape(apiKey, {
16935
17461
  strict: willFlowToProvider,
16936
- ...willFlowToProvider ? { provider: providerFromModelId(options.model?.id) } : {}
17462
+ // `options.model` is already normalized by `runCreateUnderSpan`; `normalizeModel`
17463
+ // here is the idempotent narrowing of the widened public type (`{id}` passes
17464
+ // through by reference) — cleaner than an `as` cast.
17465
+ ...willFlowToProvider ? { provider: providerFromModelId(normalizeModel(options.model)?.id) } : {}
16937
17466
  });
16938
17467
  if (shape.malformed) {
16939
17468
  throw new AuthenticationError(shape.message, { code: "malformed_api_key" });
@@ -16999,6 +17528,10 @@ async function rehydrateExistingAgent(agentId, existing, options) {
16999
17528
  ...existing.options,
17000
17529
  ...options,
17001
17530
  ...mergedLocal !== void 0 ? { local: mergedLocal } : {},
17531
+ // SE8 — normalize a caller-supplied bare-string model override at this resume
17532
+ // boundary (Agent.resume never flows through runCreateUnderSpan). Cloud resume
17533
+ // honors it; local resume forces the persisted model below.
17534
+ model: normalizeModel(options.model ?? existing.options.model),
17002
17535
  mcpServers: void 0,
17003
17536
  agentId
17004
17537
  };
@@ -17081,237 +17614,11 @@ var init_agent_helpers = __esm({
17081
17614
  init_cloud_agent();
17082
17615
  init_cloud_tool_parity();
17083
17616
  init_local_agent();
17617
+ init_model_selection();
17084
17618
  init_agent_registry();
17085
17619
  init_validate_agent_options();
17086
17620
  }
17087
17621
  });
17088
- function toJsonSchema(schema, options = { unrepresentable: "any" }) {
17089
- return zod.toJSONSchema(schema, options);
17090
- }
17091
- var init_to_json_schema = __esm({
17092
- "src/internal/zod/to-json-schema.ts"() {
17093
- }
17094
- });
17095
- function requireZod() {
17096
- if (cachedZ !== void 0) return cachedZ;
17097
- const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
17098
- let mod;
17099
- try {
17100
- mod = r("zod");
17101
- } catch (cause) {
17102
- throw new ConfigurationError(
17103
- 'Structured output requires the optional peer dependency `zod`. Add `"zod": "^3.25.0 || ^4.0.0"` to your package.json and reinstall.',
17104
- { code: "zod_not_installed", cause }
17105
- );
17106
- }
17107
- cachedZ = mod.z ?? mod;
17108
- return cachedZ;
17109
- }
17110
- function makeOutputTool(jsonSchema, onCapture) {
17111
- return {
17112
- name: "output",
17113
- description: "Call this tool with your final structured answer. Match the JSON schema exactly.",
17114
- inputSchema: jsonSchema,
17115
- handler: (input) => {
17116
- const out = onCapture(input);
17117
- if (typeof out === "string") return out;
17118
- if (out instanceof Promise) return out;
17119
- return "";
17120
- }
17121
- };
17122
- }
17123
- function buildTransientAgentOptions(params) {
17124
- return {
17125
- model: params.model,
17126
- local: params.local,
17127
- tools: [params.outputTool],
17128
- systemPrompt: params.systemPrompt ?? "You produce structured output by calling the `output` tool exactly once. Match the JSON schema.",
17129
- ...params.apiKey !== void 0 ? { apiKey: params.apiKey } : {},
17130
- ...params.providers !== void 0 ? { providers: params.providers } : {}
17131
- };
17132
- }
17133
- function extractUsage2(result) {
17134
- const u = result.usage;
17135
- if (u === void 0) return { inputTokens: 0, outputTokens: 0 };
17136
- return { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 };
17137
- }
17138
- function buildToolPrompt(prompt) {
17139
- return `${prompt}
17140
-
17141
- Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
17142
- }
17143
- function setupStructuredOutput(schema, maxRetries) {
17144
- const z7 = requireZod();
17145
- const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
17146
- return {
17147
- z: z7,
17148
- jsonSchema,
17149
- maxRetries: maxRetries ?? 1,
17150
- initialUsage: { inputTokens: 0, outputTokens: 0 }
17151
- };
17152
- }
17153
- async function disposeAndDeleteTransient(agent, deletor) {
17154
- await agent.dispose();
17155
- try {
17156
- await deletor(agent.agentId);
17157
- } catch {
17158
- }
17159
- }
17160
- var cachedZ;
17161
- var init_structured_output_helpers = __esm({
17162
- "src/internal/structured-output-helpers.ts"() {
17163
- init_errors();
17164
- init_to_json_schema();
17165
- }
17166
- });
17167
-
17168
- // src/generate-object.ts
17169
- var generate_object_exports = {};
17170
- __export(generate_object_exports, {
17171
- GenerateObjectError: () => GenerateObjectError,
17172
- generateObjectImpl: () => generateObjectImpl
17173
- });
17174
- function salvagePartial(schema, raw) {
17175
- if (typeof raw !== "object" || raw === null) return raw;
17176
- const shape = schema.shape;
17177
- if (shape === void 0 || typeof shape !== "object") return raw;
17178
- const rawObj = raw;
17179
- const out = {};
17180
- for (const [key, fieldSchema] of Object.entries(shape)) {
17181
- if (typeof fieldSchema?.safeParse !== "function") continue;
17182
- const parsed = fieldSchema.safeParse(rawObj[key]);
17183
- if (parsed.success) out[key] = parsed.data;
17184
- }
17185
- return out;
17186
- }
17187
- async function runReasoningPhase(options, deps) {
17188
- const reasoningOptions = {
17189
- model: options.model,
17190
- local: options.local,
17191
- ...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
17192
- ...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
17193
- ...options.providers !== void 0 ? { providers: options.providers } : {}
17194
- };
17195
- const reasoningAgent = await deps.create(reasoningOptions);
17196
- try {
17197
- const run = await reasoningAgent.send(options.prompt);
17198
- const result = await run.wait();
17199
- const text = result.result;
17200
- return typeof text === "string" ? text : options.prompt;
17201
- } finally {
17202
- await disposeAndDeleteTransient(reasoningAgent, deps.delete);
17203
- }
17204
- }
17205
- async function generateObjectImpl(options, deps) {
17206
- const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(
17207
- options.schema,
17208
- options.maxRetries
17209
- );
17210
- let capturedRaw;
17211
- let lastUsage = initialUsage;
17212
- const sentinel = /* @__PURE__ */ Symbol("generate-object-sentinel");
17213
- class CaptureSentinel extends Error {
17214
- constructor(captured) {
17215
- super("generate-object-capture");
17216
- this.captured = captured;
17217
- }
17218
- captured;
17219
- [sentinel] = true;
17220
- }
17221
- const outputTool = makeOutputTool(jsonSchema, (input) => {
17222
- if (capturedRaw === void 0) {
17223
- capturedRaw = input;
17224
- }
17225
- throw new CaptureSentinel(input);
17226
- });
17227
- const reasoningText = options.structuringModel !== void 0 ? await runReasoningPhase(options, deps) : void 0;
17228
- const structuringModel = options.structuringModel ?? options.model;
17229
- const structuringPrompt = reasoningText ?? options.prompt;
17230
- const agentOptions = buildTransientAgentOptions({
17231
- model: structuringModel,
17232
- local: options.local,
17233
- outputTool,
17234
- ...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
17235
- ...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
17236
- ...options.providers !== void 0 ? { providers: options.providers } : {}
17237
- });
17238
- const agent = await deps.create(agentOptions);
17239
- try {
17240
- const userMessage = buildToolPrompt(structuringPrompt);
17241
- let lastParseError;
17242
- for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
17243
- capturedRaw = void 0;
17244
- const run = await agent.send(userMessage);
17245
- const result = await run.wait();
17246
- lastUsage = extractUsage2(result);
17247
- if (capturedRaw === void 0) {
17248
- if (result.status === "error" && result.error !== void 0) {
17249
- throw new GenerateObjectError(
17250
- "no_tool_call",
17251
- `Agent run failed before the model could reply: ${result.error.message ?? "unknown error"} [${result.error.code ?? "?"}]`,
17252
- result.error
17253
- );
17254
- }
17255
- if (attempt === maxRetries) {
17256
- throw new GenerateObjectError(
17257
- "no_tool_call",
17258
- "The model returned text instead of calling the `output` tool."
17259
- );
17260
- }
17261
- continue;
17262
- }
17263
- const parsed = options.schema.safeParse(capturedRaw);
17264
- if (parsed.success) {
17265
- return {
17266
- object: parsed.data,
17267
- raw: capturedRaw,
17268
- usage: lastUsage,
17269
- finishReason: "tool_use"
17270
- };
17271
- }
17272
- lastParseError = parsed.error;
17273
- }
17274
- if (options.errorStrategy === "return-raw") {
17275
- return {
17276
- object: capturedRaw,
17277
- raw: capturedRaw,
17278
- usage: lastUsage,
17279
- finishReason: "tool_use"
17280
- };
17281
- }
17282
- if (options.errorStrategy === "return-partial") {
17283
- return {
17284
- object: salvagePartial(options.schema, capturedRaw),
17285
- raw: capturedRaw,
17286
- usage: lastUsage,
17287
- finishReason: "tool_use"
17288
- };
17289
- }
17290
- throw new GenerateObjectError(
17291
- "parse_failed",
17292
- "Schema parse failed after all retries.",
17293
- lastParseError
17294
- );
17295
- } finally {
17296
- await disposeAndDeleteTransient(agent, deps.delete);
17297
- }
17298
- }
17299
- var GenerateObjectError;
17300
- var init_generate_object = __esm({
17301
- "src/generate-object.ts"() {
17302
- init_structured_output_helpers();
17303
- GenerateObjectError = class extends Error {
17304
- name = "GenerateObjectError";
17305
- code;
17306
- cause;
17307
- constructor(code, message, cause) {
17308
- super(message);
17309
- this.code = code;
17310
- if (cause !== void 0) this.cause = cause;
17311
- }
17312
- };
17313
- }
17314
- });
17315
17622
 
17316
17623
  // src/stream-object.ts
17317
17624
  var stream_object_exports = {};
@@ -17367,7 +17674,7 @@ async function* streamObjectImpl(options, deps) {
17367
17674
  }
17368
17675
  }
17369
17676
  const result = await run.wait();
17370
- lastUsage = extractUsage2(result);
17677
+ lastUsage = extractUsage(result);
17371
17678
  if (capturedRaw === void 0) {
17372
17679
  if (result.status === "error" && result.error !== void 0) {
17373
17680
  throw new StreamObjectError(
@@ -18014,6 +18321,7 @@ var init_agent = __esm({
18014
18321
  };
18015
18322
  setAgentFacade({
18016
18323
  create: (options) => Agent.create(options),
18324
+ delete: (agentId) => Agent.delete(agentId),
18017
18325
  prompt: (message, options) => Agent.prompt(message, options),
18018
18326
  get: (agentId) => Agent.get(agentId),
18019
18327
  resume: (agentId, options) => Agent.resume(agentId, options),
@@ -18070,7 +18378,9 @@ var MessageBus = class {
18070
18378
  ...partial,
18071
18379
  from,
18072
18380
  to,
18073
- timestamp: Date.now()
18381
+ timestamp: Date.now(),
18382
+ // SE3 — provenance projection of the sender address (thin view over `from`).
18383
+ origin: { kind: "peer", from }
18074
18384
  };
18075
18385
  handler(message);
18076
18386
  }
@@ -18084,7 +18394,9 @@ var MessageBus = class {
18084
18394
  ...partial,
18085
18395
  from,
18086
18396
  to,
18087
- timestamp: Date.now()
18397
+ timestamp: Date.now(),
18398
+ // SE3 — provenance projection of the sender address (thin view over `from`).
18399
+ origin: { kind: "peer", from }
18088
18400
  };
18089
18401
  return Promise.race([
18090
18402
  Promise.resolve(handler(message)),
@@ -18114,6 +18426,52 @@ var MaxDelegationDepthError = class extends Error {
18114
18426
  maxDepth;
18115
18427
  code = "max_delegation_depth";
18116
18428
  };
18429
+ async function applyDelegationStart(spec, input) {
18430
+ if (spec.onDelegationStart === void 0) return { input };
18431
+ const decision = await spec.onDelegationStart({ input, name: spec.name });
18432
+ if (decision === void 0) return { input };
18433
+ if (decision.proceed === false)
18434
+ return { reject: decision.rejectionReason ?? "(delegation rejected)" };
18435
+ return { input: decision.modifiedInput ?? input };
18436
+ }
18437
+ async function runChildAgent(spec, input, signal) {
18438
+ const { Agent: Agent2 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
18439
+ const agent = await Agent2.create({
18440
+ ...spec.model ? { model: { id: spec.model } } : {},
18441
+ systemPrompt: spec.instructions,
18442
+ tools: spec.tools ?? []
18443
+ });
18444
+ try {
18445
+ const run = signal !== void 0 ? await agent.send(input, { signal }) : await agent.send(input);
18446
+ const result = await run.wait();
18447
+ return result.result ?? "(no response)";
18448
+ } finally {
18449
+ agent.dispose();
18450
+ }
18451
+ }
18452
+ async function notifyDelegationError(spec, input, error) {
18453
+ if (spec.onDelegationComplete === void 0) return;
18454
+ try {
18455
+ await spec.onDelegationComplete({ input, name: spec.name, error });
18456
+ } catch {
18457
+ }
18458
+ }
18459
+ function applyMessageFilter(spec, input, messages) {
18460
+ if (spec.messageFilter === void 0 || messages === void 0) return input;
18461
+ const filtered = spec.messageFilter({ messages, input, name: spec.name });
18462
+ if (filtered.length === 0) return input;
18463
+ const preamble = filtered.map((m) => `${m.role}: ${m.content}`).join("\n");
18464
+ return `Prior conversation:
18465
+ ${preamble}
18466
+
18467
+ Task:
18468
+ ${input}`;
18469
+ }
18470
+ async function applyDelegationComplete(spec, input, result) {
18471
+ if (spec.onDelegationComplete === void 0) return result;
18472
+ const completion = await spec.onDelegationComplete({ input, name: spec.name, result });
18473
+ return completion?.feedback !== void 0 ? result + completion.feedback : result;
18474
+ }
18117
18475
  function defineSubAgent(spec, _parentDepth = 0) {
18118
18476
  const currentDepth = _parentDepth + 1;
18119
18477
  const maxDepth = spec.maxDelegationDepth ?? 3;
@@ -18127,21 +18485,19 @@ function defineSubAgent(spec, _parentDepth = 0) {
18127
18485
  name: spec.name,
18128
18486
  description: spec.description,
18129
18487
  inputSchema,
18130
- handler: async (rawInput) => {
18131
- const { input } = inputSchema.parse(rawInput);
18132
- const { Agent: Agent2 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
18133
- const agent = await Agent2.create({
18134
- ...spec.model ? { model: { id: spec.model } } : {},
18135
- systemPrompt: spec.instructions,
18136
- tools: spec.tools ?? []
18137
- });
18488
+ handler: async (rawInput, ctx) => {
18489
+ const { input: parsed } = inputSchema.parse(rawInput);
18490
+ const start = await applyDelegationStart(spec, parsed);
18491
+ if ("reject" in start) return start.reject;
18492
+ const input = applyMessageFilter(spec, start.input, ctx?.messages);
18493
+ let result;
18138
18494
  try {
18139
- const run = await agent.send(input);
18140
- const result = await run.wait();
18141
- return result.result ?? "(no response)";
18142
- } finally {
18143
- agent.dispose();
18495
+ result = await runChildAgent(spec, input, ctx?.signal);
18496
+ } catch (error) {
18497
+ await notifyDelegationError(spec, input, error);
18498
+ throw error;
18144
18499
  }
18500
+ return applyDelegationComplete(spec, input, result);
18145
18501
  }
18146
18502
  };
18147
18503
  }