@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
package/dist/a2a/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { existsSync, realpathSync, mkdirSync, lstatSync, readlinkSync, readFileSync, readdirSync } from 'fs';
2
2
  import { randomUUID, createHash, randomBytes } from 'crypto';
3
- import { join, dirname, resolve, sep, relative, isAbsolute } from 'path';
4
- import { stat, mkdir, readFile, rename, rm, readdir, open, unlink, appendFile, statfs, access } from 'fs/promises';
5
- import { homedir } from 'os';
6
3
  import { z, toJSONSchema } from 'zod';
7
4
  import { createRequire } from 'module';
5
+ import { join, dirname, resolve, sep, relative, isAbsolute } from 'path';
6
+ import { stat, mkdir, readFile, rename, rm, readdir, writeFile, open, unlink, appendFile, statfs, access } from 'fs/promises';
7
+ import { homedir } from 'os';
8
8
  import { spawn } from 'child_process';
9
9
  import { AsyncLocalStorage } from 'async_hooks';
10
10
  import { fileURLToPath } from 'url';
@@ -29,6 +29,7 @@ var init_agent_builder = __esm({
29
29
  constructor(deps) {
30
30
  this.deps = deps;
31
31
  }
32
+ /** SE8 — accepts a bare-string id shorthand (`"openai/gpt-4o-mini"`) or a {@link ModelSelection}. */
32
33
  model(m) {
33
34
  this.opts.model = m;
34
35
  return this;
@@ -895,6 +896,329 @@ var init_ids = __esm({
895
896
  }
896
897
  });
897
898
 
899
+ // src/internal/runtime/config/default-model.ts
900
+ var DEFAULT_AGENTIC_MODEL_ID;
901
+ var init_default_model = __esm({
902
+ "src/internal/runtime/config/default-model.ts"() {
903
+ DEFAULT_AGENTIC_MODEL_ID = "google/gemini-2.0-flash-001";
904
+ }
905
+ });
906
+ function toJsonSchema(schema, options = { unrepresentable: "any" }) {
907
+ return toJSONSchema(schema, options);
908
+ }
909
+ var init_to_json_schema = __esm({
910
+ "src/internal/zod/to-json-schema.ts"() {
911
+ }
912
+ });
913
+ function requireZod() {
914
+ if (cachedZ !== void 0) return cachedZ;
915
+ const r = createRequire(import.meta.url);
916
+ let mod;
917
+ try {
918
+ mod = r("zod");
919
+ } catch (cause) {
920
+ throw new ConfigurationError(
921
+ 'Structured output requires the optional peer dependency `zod`. Add `"zod": "^3.25.0 || ^4.0.0"` to your package.json and reinstall.',
922
+ { code: "zod_not_installed", cause }
923
+ );
924
+ }
925
+ cachedZ = mod.z ?? mod;
926
+ return cachedZ;
927
+ }
928
+ function makeOutputTool(jsonSchema, onCapture) {
929
+ return {
930
+ name: "output",
931
+ description: "Call this tool with your final structured answer. Match the JSON schema exactly.",
932
+ inputSchema: jsonSchema,
933
+ handler: (input) => {
934
+ const out = onCapture(input);
935
+ if (typeof out === "string") return out;
936
+ if (out instanceof Promise) return out;
937
+ return "";
938
+ }
939
+ };
940
+ }
941
+ function buildTransientAgentOptions(params) {
942
+ return {
943
+ model: params.model,
944
+ local: params.local,
945
+ tools: [params.outputTool],
946
+ systemPrompt: params.systemPrompt ?? "You produce structured output by calling the `output` tool exactly once. Match the JSON schema.",
947
+ ...params.apiKey !== void 0 ? { apiKey: params.apiKey } : {},
948
+ ...params.providers !== void 0 ? { providers: params.providers } : {}
949
+ };
950
+ }
951
+ function extractUsage(result) {
952
+ const u = result.usage;
953
+ if (u === void 0) return { inputTokens: 0, outputTokens: 0 };
954
+ return { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 };
955
+ }
956
+ function buildToolPrompt(prompt) {
957
+ return `${prompt}
958
+
959
+ Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
960
+ }
961
+ function setupStructuredOutput(schema, maxRetries) {
962
+ const z7 = requireZod();
963
+ const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
964
+ return {
965
+ z: z7,
966
+ jsonSchema,
967
+ maxRetries: maxRetries ?? 1,
968
+ initialUsage: { inputTokens: 0, outputTokens: 0 }
969
+ };
970
+ }
971
+ async function disposeAndDeleteTransient(agent, deletor) {
972
+ await agent.dispose();
973
+ try {
974
+ await deletor(agent.agentId);
975
+ } catch {
976
+ }
977
+ }
978
+ var cachedZ;
979
+ var init_structured_output_helpers = __esm({
980
+ "src/internal/structured-output-helpers.ts"() {
981
+ init_errors();
982
+ init_to_json_schema();
983
+ }
984
+ });
985
+
986
+ // src/generate-object.ts
987
+ var generate_object_exports = {};
988
+ __export(generate_object_exports, {
989
+ GenerateObjectError: () => GenerateObjectError,
990
+ generateObjectImpl: () => generateObjectImpl
991
+ });
992
+ function salvagePartial(schema, raw) {
993
+ if (typeof raw !== "object" || raw === null) return raw;
994
+ const shape = schema.shape;
995
+ if (shape === void 0 || typeof shape !== "object") return raw;
996
+ const rawObj = raw;
997
+ const out = {};
998
+ for (const [key, fieldSchema] of Object.entries(shape)) {
999
+ if (typeof fieldSchema?.safeParse !== "function") continue;
1000
+ const parsed = fieldSchema.safeParse(rawObj[key]);
1001
+ if (parsed.success) out[key] = parsed.data;
1002
+ }
1003
+ return out;
1004
+ }
1005
+ async function runReasoningPhase(options, deps) {
1006
+ const reasoningOptions = {
1007
+ model: options.model,
1008
+ local: options.local,
1009
+ ...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
1010
+ ...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
1011
+ ...options.providers !== void 0 ? { providers: options.providers } : {}
1012
+ };
1013
+ const reasoningAgent = await deps.create(reasoningOptions);
1014
+ try {
1015
+ const run = await reasoningAgent.send(options.prompt);
1016
+ const result = await run.wait();
1017
+ const text = result.result;
1018
+ return typeof text === "string" ? text : options.prompt;
1019
+ } finally {
1020
+ await disposeAndDeleteTransient(reasoningAgent, deps.delete);
1021
+ }
1022
+ }
1023
+ async function generateObjectImpl(options, deps) {
1024
+ const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(
1025
+ options.schema,
1026
+ options.maxRetries
1027
+ );
1028
+ let capturedRaw;
1029
+ let lastUsage = initialUsage;
1030
+ const sentinel = /* @__PURE__ */ Symbol("generate-object-sentinel");
1031
+ class CaptureSentinel extends Error {
1032
+ constructor(captured) {
1033
+ super("generate-object-capture");
1034
+ this.captured = captured;
1035
+ }
1036
+ captured;
1037
+ [sentinel] = true;
1038
+ }
1039
+ const outputTool = makeOutputTool(jsonSchema, (input) => {
1040
+ if (capturedRaw === void 0) {
1041
+ capturedRaw = input;
1042
+ }
1043
+ throw new CaptureSentinel(input);
1044
+ });
1045
+ const reasoningText = options.structuringModel !== void 0 ? await runReasoningPhase(options, deps) : void 0;
1046
+ const structuringModel = options.structuringModel ?? options.model;
1047
+ const structuringPrompt = reasoningText ?? options.prompt;
1048
+ const agentOptions = buildTransientAgentOptions({
1049
+ model: structuringModel,
1050
+ local: options.local,
1051
+ outputTool,
1052
+ ...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
1053
+ ...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
1054
+ ...options.providers !== void 0 ? { providers: options.providers } : {}
1055
+ });
1056
+ const agent = await deps.create(agentOptions);
1057
+ try {
1058
+ const userMessage = buildToolPrompt(structuringPrompt);
1059
+ let lastParseError;
1060
+ for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
1061
+ capturedRaw = void 0;
1062
+ const run = await agent.send(userMessage);
1063
+ const result = await run.wait();
1064
+ lastUsage = extractUsage(result);
1065
+ if (capturedRaw === void 0) {
1066
+ if (result.status === "error" && result.error !== void 0) {
1067
+ throw new GenerateObjectError(
1068
+ "no_tool_call",
1069
+ `Agent run failed before the model could reply: ${result.error.message ?? "unknown error"} [${result.error.code ?? "?"}]`,
1070
+ result.error
1071
+ );
1072
+ }
1073
+ if (attempt === maxRetries) {
1074
+ throw new GenerateObjectError(
1075
+ "no_tool_call",
1076
+ "The model returned text instead of calling the `output` tool."
1077
+ );
1078
+ }
1079
+ continue;
1080
+ }
1081
+ const parsed = options.schema.safeParse(capturedRaw);
1082
+ if (parsed.success) {
1083
+ return {
1084
+ object: parsed.data,
1085
+ raw: capturedRaw,
1086
+ usage: lastUsage,
1087
+ finishReason: "tool_use"
1088
+ };
1089
+ }
1090
+ lastParseError = parsed.error;
1091
+ }
1092
+ if (options.errorStrategy === "return-raw") {
1093
+ return {
1094
+ object: capturedRaw,
1095
+ raw: capturedRaw,
1096
+ usage: lastUsage,
1097
+ finishReason: "tool_use"
1098
+ };
1099
+ }
1100
+ if (options.errorStrategy === "return-partial") {
1101
+ return {
1102
+ object: salvagePartial(options.schema, capturedRaw),
1103
+ raw: capturedRaw,
1104
+ usage: lastUsage,
1105
+ finishReason: "tool_use"
1106
+ };
1107
+ }
1108
+ throw new GenerateObjectError(
1109
+ "parse_failed",
1110
+ "Schema parse failed after all retries.",
1111
+ lastParseError
1112
+ );
1113
+ } finally {
1114
+ await disposeAndDeleteTransient(agent, deps.delete);
1115
+ }
1116
+ }
1117
+ var GenerateObjectError;
1118
+ var init_generate_object = __esm({
1119
+ "src/generate-object.ts"() {
1120
+ init_structured_output_helpers();
1121
+ GenerateObjectError = class extends Error {
1122
+ name = "GenerateObjectError";
1123
+ code;
1124
+ cause;
1125
+ constructor(code, message, cause) {
1126
+ super(message);
1127
+ this.code = code;
1128
+ if (cause !== void 0) this.cause = cause;
1129
+ }
1130
+ };
1131
+ }
1132
+ });
1133
+
1134
+ // src/internal/runtime/registry/agent-factory-registry.ts
1135
+ var agent_factory_registry_exports = {};
1136
+ __export(agent_factory_registry_exports, {
1137
+ getAgentFacade: () => getAgentFacade,
1138
+ setAgentFacade: () => setAgentFacade
1139
+ });
1140
+ function setAgentFacade(facade) {
1141
+ registered = facade;
1142
+ }
1143
+ function getAgentFacade() {
1144
+ if (registered === void 0) {
1145
+ throw new Error(
1146
+ "internal: Agent facade not registered. The `agent.ts` module must be loaded before internal subsystems (LocalAgent.runUntil/fork, eval, scorers, cron) invoke it."
1147
+ );
1148
+ }
1149
+ return registered;
1150
+ }
1151
+ var registered;
1152
+ var init_agent_factory_registry = __esm({
1153
+ "src/internal/runtime/registry/agent-factory-registry.ts"() {
1154
+ }
1155
+ });
1156
+
1157
+ // src/agent-generate.ts
1158
+ async function agentGenerate(agent, agentModel, agentApiKey, agentLocal, input, options) {
1159
+ const { output, maxRetries, errorStrategy, ...sendOptions } = options;
1160
+ const run = await agent.send(input, sendOptions);
1161
+ const result = await run.wait();
1162
+ const { generateObjectImpl: generateObjectImpl2, GenerateObjectError: GenerateObjectError2 } = await Promise.resolve().then(() => (init_generate_object(), generate_object_exports));
1163
+ const answer = structurableAnswerOrThrow(result, GenerateObjectError2);
1164
+ const { getAgentFacade: getAgentFacade2 } = await Promise.resolve().then(() => (init_agent_factory_registry(), agent_factory_registry_exports));
1165
+ const facade = getAgentFacade2();
1166
+ const structured = await generateObjectImpl2(
1167
+ {
1168
+ prompt: answer,
1169
+ schema: output,
1170
+ // `agentModel` arrives already normalized (`this.model` passed through
1171
+ // `normalizeModel` in the LocalAgent/CloudAgent constructor), so the widened
1172
+ // `string | ModelSelection` field only ever receives a `ModelSelection` here.
1173
+ model: agentModel ?? { id: DEFAULT_AGENTIC_MODEL_ID },
1174
+ // `local` is required to keep the transient structuring agent local-only;
1175
+ // default to the process cwd when the agent had no explicit local config.
1176
+ local: agentLocal ?? { cwd: process.cwd() },
1177
+ ...agentApiKey !== void 0 ? { apiKey: agentApiKey } : {},
1178
+ ...maxRetries !== void 0 ? { maxRetries } : {},
1179
+ ...errorStrategy !== void 0 ? { errorStrategy } : {}
1180
+ },
1181
+ {
1182
+ create: (opts) => facade.create(opts),
1183
+ delete: (agentId) => facade.delete(agentId)
1184
+ }
1185
+ );
1186
+ return {
1187
+ object: structured.object,
1188
+ result,
1189
+ raw: structured.raw,
1190
+ usage: structured.usage
1191
+ };
1192
+ }
1193
+ function structurableAnswerOrThrow(result, GenerateObjectError2) {
1194
+ if (result.status === "error") {
1195
+ throw new GenerateObjectError2(
1196
+ "no_tool_call",
1197
+ `Agent run failed before an answer could be structured: ${result.error?.message ?? "unknown error"} [${result.error?.code ?? "?"}]`,
1198
+ result.error
1199
+ );
1200
+ }
1201
+ if (result.status === "cancelled") {
1202
+ throw new GenerateObjectError2(
1203
+ "no_tool_call",
1204
+ "Agent run was cancelled before an answer could be structured."
1205
+ );
1206
+ }
1207
+ const answer = result.result;
1208
+ if (answer === void 0 || answer.length === 0) {
1209
+ throw new GenerateObjectError2(
1210
+ "no_tool_call",
1211
+ "The tool loop finished with no text answer (tool-only completion) \u2014 there is nothing to structure."
1212
+ );
1213
+ }
1214
+ return answer;
1215
+ }
1216
+ var init_agent_generate = __esm({
1217
+ "src/agent-generate.ts"() {
1218
+ init_default_model();
1219
+ }
1220
+ });
1221
+
898
1222
  // src/internal/persistence/cwd-mutex.ts
899
1223
  function withCwdMutex(key, fn) {
900
1224
  const prev = tails.get(key) ?? Promise.resolve();
@@ -1064,11 +1388,21 @@ var init_path_guard = __esm({
1064
1388
  }
1065
1389
  });
1066
1390
 
1067
- // src/internal/runtime/config/default-model.ts
1068
- var DEFAULT_AGENTIC_MODEL_ID;
1069
- var init_default_model = __esm({
1070
- "src/internal/runtime/config/default-model.ts"() {
1071
- DEFAULT_AGENTIC_MODEL_ID = "google/gemini-2.0-flash-001";
1391
+ // src/internal/runtime/model-selection.ts
1392
+ function normalizeModel(m) {
1393
+ if (m === void 0 || typeof m !== "string") return m;
1394
+ const id = m.trim();
1395
+ if (id.length === 0) {
1396
+ throw new ConfigurationError(
1397
+ 'model must be a non-empty "provider/model" id string or a ModelSelection object',
1398
+ { code: "invalid_model_selection" }
1399
+ );
1400
+ }
1401
+ return { id };
1402
+ }
1403
+ var init_model_selection = __esm({
1404
+ "src/internal/runtime/model-selection.ts"() {
1405
+ init_errors();
1072
1406
  }
1073
1407
  });
1074
1408
  function detectNetworkFsName(typeMagic) {
@@ -1208,7 +1542,10 @@ var init_enabled_names = __esm({
1208
1542
  function stripSecretsFromOptions(options) {
1209
1543
  return assignDefined({
1210
1544
  name: options.name,
1211
- model: options.model !== void 0 ? { id: options.model.id } : void 0,
1545
+ model: (() => {
1546
+ const m = normalizeModel(options.model);
1547
+ return m !== void 0 ? { id: m.id } : void 0;
1548
+ })(),
1212
1549
  systemPrompt: typeof options.systemPrompt === "string" ? options.systemPrompt : void 0,
1213
1550
  local: serializeLocal(options.local),
1214
1551
  cloud: serializeCloud(options.cloud),
@@ -1379,6 +1716,7 @@ var init_agent_registry_store = __esm({
1379
1716
  init_cwd_mutex();
1380
1717
  init_schema_version();
1381
1718
  init_enabled_names();
1719
+ init_model_selection();
1382
1720
  SCHEMA_VERSION = 1;
1383
1721
  LEGACY_SCHEMA_VERSION_STRING = "1.0";
1384
1722
  REGISTRY_RELATIVE_PATH = join(".theokit", "agents", "registry.json");
@@ -1514,7 +1852,8 @@ function serializeCloudAgentConfig(options) {
1514
1852
  cloud: serializeCloud2(options.cloud)
1515
1853
  };
1516
1854
  if (typeof options.agentId === "string") payload.agentId = options.agentId;
1517
- if (options.model !== void 0) payload.model = { id: options.model.id };
1855
+ const cfgModel = normalizeModel(options.model);
1856
+ if (cfgModel !== void 0) payload.model = { id: cfgModel.id };
1518
1857
  if (typeof options.systemPrompt === "string") payload.systemPrompt = options.systemPrompt;
1519
1858
  const skills = serializeSkills(options.skills);
1520
1859
  if (skills !== void 0) payload.skills = skills;
@@ -1624,6 +1963,7 @@ function serializeMemory2(memory) {
1624
1963
  var init_cloud_config_serializer = __esm({
1625
1964
  "src/internal/runtime/cloud/cloud-config-serializer.ts"() {
1626
1965
  init_enabled_names();
1966
+ init_model_selection();
1627
1967
  }
1628
1968
  });
1629
1969
 
@@ -2334,6 +2674,7 @@ function applyScriptMetrics(base, script) {
2334
2674
  if (script.cost !== void 0) base.cost = script.cost;
2335
2675
  if (script.stoppedAtIterationLimit === true) base.stoppedAtIterationLimit = true;
2336
2676
  if (script.stoppedByDoomLoop === true) base.stoppedByDoomLoop = true;
2677
+ if (script.origin !== void 0) base.origin = script.origin;
2337
2678
  }
2338
2679
  var FixtureRunBase;
2339
2680
  var init_fixture_run_base = __esm({
@@ -2841,6 +3182,7 @@ function buildFixtureArtifacts() {
2841
3182
  var CloudAgent;
2842
3183
  var init_cloud_agent = __esm({
2843
3184
  "src/internal/runtime/cloud/cloud-agent.ts"() {
3185
+ init_agent_generate();
2844
3186
  init_errors();
2845
3187
  init_env();
2846
3188
  init_fixture_mode();
@@ -2848,6 +3190,7 @@ var init_cloud_agent = __esm({
2848
3190
  init_cwd_mutex();
2849
3191
  init_path_guard();
2850
3192
  init_default_model();
3193
+ init_model_selection();
2851
3194
  init_agent_registry();
2852
3195
  init_system_prompt();
2853
3196
  init_cloud_config_serializer();
@@ -2867,7 +3210,7 @@ var init_cloud_agent = __esm({
2867
3210
  disposed = false;
2868
3211
  constructor(options, providedAgentId) {
2869
3212
  this.agentId = providedAgentId ?? options.agentId ?? generateCloudAgentId();
2870
- this.model = options.model;
3213
+ this.model = normalizeModel(options.model);
2871
3214
  this.options = options;
2872
3215
  this.cloudPayload = serializeCloudAgentConfig({ ...options, agentId: this.agentId });
2873
3216
  const repoUrls = (options.cloud?.repos ?? []).map((repo) => repo.url);
@@ -2897,6 +3240,17 @@ var init_cloud_agent = __esm({
2897
3240
  const apiKey = resolveApiKey(this.options.apiKey);
2898
3241
  return isFixtureApiKey(apiKey) && getConfiguredBaseUrl() === void 0;
2899
3242
  }
3243
+ // SE9 — integrated structured output; delegates to the shared helper.
3244
+ generate(message, options) {
3245
+ return agentGenerate(
3246
+ this,
3247
+ this.model,
3248
+ this.options.apiKey,
3249
+ this.options.local,
3250
+ message,
3251
+ options
3252
+ );
3253
+ }
2900
3254
  async send(message, options = {}) {
2901
3255
  if (options.tools !== void 0 && options.tools.length > 0) {
2902
3256
  throw new ConfigurationError(
@@ -2927,7 +3281,7 @@ var init_cloud_agent = __esm({
2927
3281
  });
2928
3282
  }
2929
3283
  async sendLocked(message, options) {
2930
- const overrideModel = options.model;
3284
+ const overrideModel = normalizeModel(options.model);
2931
3285
  if (overrideModel !== void 0) {
2932
3286
  this.model = overrideModel;
2933
3287
  updateRegisteredAgent(this.agentId, { model: overrideModel });
@@ -4121,12 +4475,12 @@ function tryAutoRegisterAdapters(settings) {
4121
4475
  if (settings.autoDetect === false) return;
4122
4476
  const disabled = new Set(settings.disable ?? []);
4123
4477
  for (const adapter of ALL_ADAPTERS) {
4124
- if (registered.has(adapter.moduleName)) continue;
4478
+ if (registered2.has(adapter.moduleName)) continue;
4125
4479
  if (disabled.has(adapter.displayName.toLowerCase())) continue;
4126
4480
  if (!adapter.detect()) continue;
4127
4481
  try {
4128
4482
  adapter.register();
4129
- registered.add(adapter.moduleName);
4483
+ registered2.add(adapter.moduleName);
4130
4484
  process.stderr.write(`[theokit-sdk] telemetry: ${adapter.displayName} auto-instrumented.
4131
4485
  `);
4132
4486
  } catch (cause) {
@@ -4138,7 +4492,7 @@ function tryAutoRegisterAdapters(settings) {
4138
4492
  }
4139
4493
  }
4140
4494
  }
4141
- var ALL_ADAPTERS, registered;
4495
+ var ALL_ADAPTERS, registered2;
4142
4496
  var init_adapter_registry = __esm({
4143
4497
  "src/internal/telemetry/adapter-registry.ts"() {
4144
4498
  init_arize();
@@ -4157,7 +4511,7 @@ var init_adapter_registry = __esm({
4157
4511
  arizeAdapter,
4158
4512
  braintrustAdapter
4159
4513
  ];
4160
- registered = /* @__PURE__ */ new Set();
4514
+ registered2 = /* @__PURE__ */ new Set();
4161
4515
  }
4162
4516
  });
4163
4517
  function loadOtel() {
@@ -4748,6 +5102,30 @@ var init_pagination = __esm({
4748
5102
  "src/internal/persistence/pagination.ts"() {
4749
5103
  }
4750
5104
  });
5105
+
5106
+ // src/internal/persistence/session-meta.ts
5107
+ function applyMetaPatch(current, patch) {
5108
+ const next = {};
5109
+ if (current.title !== void 0) next.title = current.title;
5110
+ if (current.tag !== void 0) next.tag = current.tag;
5111
+ if (patch.title === null) delete next.title;
5112
+ else if (patch.title !== void 0) next.title = patch.title;
5113
+ if (patch.tag === null) delete next.tag;
5114
+ else if (patch.tag !== void 0) next.tag = patch.tag;
5115
+ return next;
5116
+ }
5117
+ function coerceSessionMeta(raw) {
5118
+ if (typeof raw !== "object" || raw === null) return void 0;
5119
+ const obj = raw;
5120
+ const meta = {};
5121
+ if (typeof obj.title === "string") meta.title = obj.title;
5122
+ if (typeof obj.tag === "string") meta.tag = obj.tag;
5123
+ return meta.title === void 0 && meta.tag === void 0 ? void 0 : meta;
5124
+ }
5125
+ var init_session_meta = __esm({
5126
+ "src/internal/persistence/session-meta.ts"() {
5127
+ }
5128
+ });
4751
5129
  function toStoredMessage(record) {
4752
5130
  return {
4753
5131
  role: record.role,
@@ -4763,7 +5141,9 @@ var init_conversation_storage_fs = __esm({
4763
5141
  "src/internal/persistence/conversation-storage-fs.ts"() {
4764
5142
  init_agent_session_store();
4765
5143
  init_security();
5144
+ init_file_lock();
4766
5145
  init_pagination();
5146
+ init_session_meta();
4767
5147
  FileSystemConversationStorage = class {
4768
5148
  #root;
4769
5149
  constructor(opts = {}) {
@@ -4813,6 +5193,37 @@ var init_conversation_storage_fs = __esm({
4813
5193
  async compact(conversationId, maxTurns) {
4814
5194
  await compactSessionFile(this.#root, conversationId, maxTurns);
4815
5195
  }
5196
+ // SE4 — session metadata persisted as a per-conversation sidecar
5197
+ // `<root>/.theokit/agents/<safeId>/session.json` (same sanitized perimeter as
5198
+ // the transcript). Kept separate from messages.jsonl so a title/tag write does
5199
+ // not rewrite the append-only log.
5200
+ #metaPath(conversationId) {
5201
+ const safe2 = sanitizeIdentifier(conversationId, { maxLen: 128 });
5202
+ return safePathJoin(this.#root, ".theokit", "agents", safe2, "session.json");
5203
+ }
5204
+ async getSessionMeta(conversationId) {
5205
+ try {
5206
+ const raw = await readFile(this.#metaPath(conversationId), "utf8");
5207
+ return coerceSessionMeta(JSON.parse(raw));
5208
+ } catch (cause) {
5209
+ if (cause.code === "ENOENT") return void 0;
5210
+ throw cause;
5211
+ }
5212
+ }
5213
+ async setSessionMeta(conversationId, patch) {
5214
+ const metaPath = this.#metaPath(conversationId);
5215
+ await mkdir(dirname(metaPath), { recursive: true });
5216
+ await withFileLock(metaPath, async () => {
5217
+ let current = {};
5218
+ try {
5219
+ current = coerceSessionMeta(JSON.parse(await readFile(metaPath, "utf8"))) ?? {};
5220
+ } catch (cause) {
5221
+ if (cause.code !== "ENOENT") throw cause;
5222
+ }
5223
+ const next = applyMetaPatch(current, patch);
5224
+ await writeFile(metaPath, redactSecrets(JSON.stringify(next)), "utf8");
5225
+ });
5226
+ }
4816
5227
  async dispose() {
4817
5228
  }
4818
5229
  };
@@ -6876,7 +7287,7 @@ function bootstrapSubmanagers(args) {
6876
7287
  const providerCount = (args.options.providers?.routes?.length ?? 0) + enabledPluginNames(args.options.plugins).length;
6877
7288
  if (providerCount > 0 || args.options.providers !== void 0) {
6878
7289
  out.providers = new ProvidersManagerImpl(
6879
- args.options.model,
7290
+ normalizeModel(args.options.model),
6880
7291
  args.options.providers,
6881
7292
  args.options.plugins
6882
7293
  );
@@ -6913,6 +7324,7 @@ var init_local_agent_bootstrap = __esm({
6913
7324
  init_enabled_names();
6914
7325
  init_providers_manager();
6915
7326
  init_context_manager();
7327
+ init_model_selection();
6916
7328
  init_plugins_manager();
6917
7329
  init_agent_registry();
6918
7330
  init_skills_manager();
@@ -6961,6 +7373,7 @@ function createLocalRun(options) {
6961
7373
  projectMcpServers: options.projectMcpServers,
6962
7374
  ...options.persistMemoryFact !== void 0 ? { persistMemoryFact: options.persistMemoryFact } : {}
6963
7375
  });
7376
+ if (options.sendOptions.origin !== void 0) script.origin = options.sendOptions.origin;
6964
7377
  const handle = new LocalRun({
6965
7378
  id,
6966
7379
  agentId: options.agentId,
@@ -7661,6 +8074,19 @@ var init_loop_llm_stream = __esm({
7661
8074
  init_message_builders();
7662
8075
  }
7663
8076
  });
8077
+
8078
+ // src/types/run-events.ts
8079
+ function emitRunEvent(sink, event) {
8080
+ if (sink === void 0) return;
8081
+ try {
8082
+ sink(event);
8083
+ } catch {
8084
+ }
8085
+ }
8086
+ var init_run_events = __esm({
8087
+ "src/types/run-events.ts"() {
8088
+ }
8089
+ });
7664
8090
  async function withToolWhitelist(whitelist, fn) {
7665
8091
  return toolWhitelistStore.run(whitelist, fn);
7666
8092
  }
@@ -7832,6 +8258,27 @@ var init_repair_middleware = __esm({
7832
8258
  }
7833
8259
  });
7834
8260
 
8261
+ // src/tool-error.ts
8262
+ function renderToolErrorMessage(content) {
8263
+ if (typeof content === "string") return content;
8264
+ return content.map((block) => block.type === "text" ? block.text : `[${block.source.media_type} image]`).join("\n");
8265
+ }
8266
+ var ToolError;
8267
+ var init_tool_error = __esm({
8268
+ "src/tool-error.ts"() {
8269
+ init_errors();
8270
+ ToolError = class extends TheokitAgentError {
8271
+ name = "ToolError";
8272
+ /** The error content surfaced to the model: a string, or text/image blocks. */
8273
+ content;
8274
+ constructor(content, options = {}) {
8275
+ super(renderToolErrorMessage(content), { ...options, isRetryable: false });
8276
+ this.content = content;
8277
+ }
8278
+ };
8279
+ }
8280
+ });
8281
+
7835
8282
  // src/internal/runtime/tools/shell-tool.ts
7836
8283
  async function runShell(options) {
7837
8284
  if (options.sandbox === true && isObviouslyUnsafe(options.command)) {
@@ -7876,23 +8323,27 @@ async function executeTool(inputs, resolved, call) {
7876
8323
  if (resolved.origin === "shell") return runShellTool(inputs, call);
7877
8324
  if (resolved.origin === "memory") return runMemoryTool(resolved, call, inputs.context);
7878
8325
  if (resolved.origin === "custom")
7879
- return runCustomTool(resolved, call, inputs.signal, inputs.context);
8326
+ return runCustomTool(resolved, call, inputs.signal, inputs.context, inputs.messages);
7880
8327
  return runMcpTool(inputs, resolved, call);
7881
8328
  }
7882
8329
  async function runMemoryTool(resolved, call, context) {
7883
8330
  return runHandlerTool("memory", resolved.memoryHandler, call, void 0, context);
7884
8331
  }
7885
- async function runCustomTool(resolved, call, signal, context) {
7886
- return runHandlerTool("custom", resolved.customHandler, call, signal, context);
8332
+ async function runCustomTool(resolved, call, signal, context, messages) {
8333
+ return runHandlerTool("custom", resolved.customHandler, call, signal, context, messages);
7887
8334
  }
7888
- async function runHandlerTool(kind, handler, call, signal, context) {
8335
+ async function runHandlerTool(kind, handler, call, signal, context, messages) {
7889
8336
  if (handler === void 0) {
7890
8337
  return { stdout: "", stderr: `${kind} tool ${call.name} has no handler`, exitCode: 127 };
7891
8338
  }
7892
8339
  try {
7893
- const stdout = await handler(call.input, { signal, context });
7894
- return { stdout, stderr: "", exitCode: 0 };
8340
+ const out = await handler(call.input, { signal, context, messages });
8341
+ if (typeof out !== "string") return { stdout: "", stderr: "", exitCode: 0, content: out };
8342
+ return { stdout: out, stderr: "", exitCode: 0 };
7895
8343
  } catch (cause) {
8344
+ if (cause instanceof ToolError) {
8345
+ return { stdout: "", stderr: cause.message, exitCode: 1, content: cause.content };
8346
+ }
7896
8347
  const message = cause instanceof Error ? cause.message : String(cause);
7897
8348
  return { stdout: "", stderr: message, exitCode: 1 };
7898
8349
  }
@@ -7937,6 +8388,7 @@ ${result.stderr}`.trim();
7937
8388
  }
7938
8389
  var init_tool_executors = __esm({
7939
8390
  "src/internal/agent-loop/tool-executors.ts"() {
8391
+ init_tool_error();
7940
8392
  init_shell_tool();
7941
8393
  }
7942
8394
  });
@@ -8021,6 +8473,11 @@ async function dispatchSingleCall(inputs, tools, call, events, parentSpan) {
8021
8473
  toolSpan?.end();
8022
8474
  return fileVeto;
8023
8475
  }
8476
+ emitRunEvent(inputs.runEventSink, {
8477
+ type: "tool_progress",
8478
+ toolName: workingCall.name,
8479
+ toolCallId: callId
8480
+ });
8024
8481
  const result = await runToolWithLifecycle(inputs, resolved, workingCall, callId);
8025
8482
  await inputs.pluginManager?.runPostToolCallHooks({
8026
8483
  name: workingCall.name,
@@ -8047,6 +8504,13 @@ function applyRepairAndExtractCall(tools, call) {
8047
8504
  function vetoFromForkWhitelist(inputs, call, callId, events) {
8048
8505
  const whitelistDecision = checkToolWhitelist(call.name);
8049
8506
  if (whitelistDecision.allowed) return void 0;
8507
+ emitRunEvent(inputs.runEventSink, {
8508
+ type: "permission_denied",
8509
+ toolName: call.name,
8510
+ toolCallId: callId,
8511
+ source: "fork_whitelist",
8512
+ message: whitelistDecision.reason ?? "tool not available in fork"
8513
+ });
8050
8514
  events.push(buildToolUseRunning(inputs, callId, call));
8051
8515
  events.push(
8052
8516
  buildToolUseCompleted(inputs, callId, call, {
@@ -8083,6 +8547,13 @@ async function vetoFromPluginPreHook(inputs, call, callId, events) {
8083
8547
  runId: inputs.runId
8084
8548
  });
8085
8549
  if (pluginVeto === void 0) return void 0;
8550
+ emitRunEvent(inputs.runEventSink, {
8551
+ type: "permission_denied",
8552
+ toolName: call.name,
8553
+ toolCallId: callId,
8554
+ source: "plugin",
8555
+ message: pluginVeto.message
8556
+ });
8086
8557
  events.push(
8087
8558
  buildToolUseCompleted(inputs, callId, call, {
8088
8559
  stdout: "",
@@ -8105,6 +8576,13 @@ async function vetoFromFileHookPreDecision(inputs, call, callId, events) {
8105
8576
  runId: inputs.runId
8106
8577
  });
8107
8578
  if (!preDecision.blocked) return void 0;
8579
+ emitRunEvent(inputs.runEventSink, {
8580
+ type: "permission_denied",
8581
+ toolName: call.name,
8582
+ toolCallId: callId,
8583
+ source: "file_hook",
8584
+ message: preDecision.reason ?? "blocked by hook"
8585
+ });
8108
8586
  events.push(
8109
8587
  buildToolUseCompleted(inputs, callId, call, {
8110
8588
  stdout: "",
@@ -8148,7 +8626,9 @@ async function runToolWithLifecycle(inputs, resolved, call, callId) {
8148
8626
  await safeEmitToolHook(inputs.onToolEnd, {
8149
8627
  toolName: call.name,
8150
8628
  args: call.input,
8151
- result: result.stdout,
8629
+ // SE7 — a block-returning handler has empty `stdout`; surface its structured
8630
+ // content to the hook instead of an empty string.
8631
+ result: result.content !== void 0 ? result.content : result.stdout,
8152
8632
  conversationId: inputs.agentId,
8153
8633
  callId,
8154
8634
  durationMs
@@ -8170,7 +8650,10 @@ function finalizeSpanAndPostHook(inputs, call, callId, result, events, toolSpan)
8170
8650
  output: {
8171
8651
  stdout: result.stdout,
8172
8652
  stderr: result.stderr,
8173
- exitCode: result.exitCode ?? 0
8653
+ exitCode: result.exitCode ?? 0,
8654
+ // SE7 — structured content (text + image blocks) when the handler
8655
+ // returned/threw blocks; absent for the string path.
8656
+ ...result.content !== void 0 ? { content: result.content } : {}
8174
8657
  },
8175
8658
  agentId: inputs.agentId,
8176
8659
  runId: inputs.runId
@@ -8183,7 +8666,9 @@ function finalizeSpanAndPostHook(inputs, call, callId, result, events, toolSpan)
8183
8666
  return {
8184
8667
  type: "tool_result",
8185
8668
  toolUseId: call.id,
8186
- content: renderToolResult(result),
8669
+ // SE7 — structured content blocks (handler-returned or ToolError-carried)
8670
+ // are authoritative; otherwise the legacy string rendering.
8671
+ content: result.content !== void 0 ? result.content : renderToolResult(result),
8187
8672
  ...result.exitCode !== 0 && result.exitCode !== void 0 ? { isError: true } : {}
8188
8673
  };
8189
8674
  }
@@ -8233,6 +8718,7 @@ function buildToolUseCompleted(inputs, callId, call, result) {
8233
8718
  }
8234
8719
  var init_tool_dispatch = __esm({
8235
8720
  "src/internal/agent-loop/tool-dispatch.ts"() {
8721
+ init_run_events();
8236
8722
  init_ids();
8237
8723
  init_async_local_storage();
8238
8724
  init_map_with_concurrency();
@@ -8243,6 +8729,33 @@ var init_tool_dispatch = __esm({
8243
8729
  }
8244
8730
  });
8245
8731
 
8732
+ // src/internal/llm/tool-result-content.ts
8733
+ function toBlockToolResultContent(content) {
8734
+ return content;
8735
+ }
8736
+ function toStringToolResultContent(content, providerName) {
8737
+ if (typeof content === "string") return content;
8738
+ if (content.some((block) => block.type === "image")) {
8739
+ throw new ConfigurationError(
8740
+ `provider "${providerName}" does not support image content in tool results`
8741
+ );
8742
+ }
8743
+ return content.filter(
8744
+ (block) => block.type === "text"
8745
+ ).map((block) => block.text).join("\n");
8746
+ }
8747
+ function renderToolResultContentText(content, fn) {
8748
+ if (typeof content === "string") return fn(content);
8749
+ return content.map(
8750
+ (block) => block.type === "text" ? { type: "text", text: fn(block.text) } : block
8751
+ );
8752
+ }
8753
+ var init_tool_result_content = __esm({
8754
+ "src/internal/llm/tool-result-content.ts"() {
8755
+ init_errors();
8756
+ }
8757
+ });
8758
+
8246
8759
  // src/internal/agent-loop/tool-result-guard.ts
8247
8760
  function guardText(content, opts) {
8248
8761
  let out = content;
@@ -8260,12 +8773,17 @@ ${CLOSE}`;
8260
8773
  function applyToolResultGuard(parts, opts) {
8261
8774
  if (opts.delimit !== true && opts.redactPii !== true) return parts;
8262
8775
  return parts.map(
8263
- (p) => p.type === "tool_result" ? { ...p, content: guardText(p.content, opts) } : p
8776
+ (p) => (
8777
+ // SE7 — guard the TEXT of a tool result (string or the text blocks of a
8778
+ // structured content); image blocks pass through untouched.
8779
+ p.type === "tool_result" ? { ...p, content: renderToolResultContentText(p.content, (t) => guardText(t, opts)) } : p
8780
+ )
8264
8781
  );
8265
8782
  }
8266
8783
  var OPEN, CLOSE, PII_PATTERNS;
8267
8784
  var init_tool_result_guard = __esm({
8268
8785
  "src/internal/agent-loop/tool-result-guard.ts"() {
8786
+ init_tool_result_content();
8269
8787
  OPEN = "<untrusted-tool-output>";
8270
8788
  CLOSE = "</untrusted-tool-output>";
8271
8789
  PII_PATTERNS = [
@@ -8644,6 +9162,14 @@ var init_usage_and_cost = __esm({
8644
9162
  });
8645
9163
 
8646
9164
  // src/internal/agent-loop/loop.ts
9165
+ function projectToolContextMessages(messages) {
9166
+ const projected = [];
9167
+ for (const m of messages) {
9168
+ const content = m.content.flatMap((p) => p.type === "text" ? [p.text] : []).join("");
9169
+ if (content !== "") projected.push({ role: m.role, content });
9170
+ }
9171
+ return projected;
9172
+ }
8647
9173
  async function runAgentLoop(inputs) {
8648
9174
  const sendSpan = inputs.telemetry?.startSpan("agent.send", {
8649
9175
  agentId: inputs.agentId,
@@ -8884,7 +9410,9 @@ async function continueOrTerminate(inputs, ctx, llmOutput) {
8884
9410
  const outText = await transformLlmOutputText(inputs, llmOutput.text, tCtx);
8885
9411
  ctx.messages.push(buildAssistantTurn(outText, llmOutput.toolCalls));
8886
9412
  const rawResults = await dispatchTools(
8887
- inputs,
9413
+ // SE12 — forward a read-only text projection of the transcript-so-far to tool
9414
+ // handlers via `ctx.messages` (consumed by defineSubAgent's messageFilter).
9415
+ { ...inputs, messages: projectToolContextMessages(ctx.messages) },
8888
9416
  ctx.tools,
8889
9417
  llmOutput.toolCalls,
8890
9418
  ctx.events,
@@ -9298,8 +9826,8 @@ var init_vertex = __esm({
9298
9826
 
9299
9827
  // src/internal/providers/builtin/index.ts
9300
9828
  function registerBuiltins() {
9301
- if (registered2) return;
9302
- registered2 = true;
9829
+ if (registered3) return;
9830
+ registered3 = true;
9303
9831
  registerProvider(ANTHROPIC);
9304
9832
  registerProvider(OPENAI);
9305
9833
  registerProvider(OPENROUTER);
@@ -9311,7 +9839,7 @@ function registerBuiltins() {
9311
9839
  registerProvider(VERTEX);
9312
9840
  registerCatalogProviders();
9313
9841
  }
9314
- var registered2;
9842
+ var registered3;
9315
9843
  var init_builtin = __esm({
9316
9844
  "src/internal/providers/builtin/index.ts"() {
9317
9845
  init_catalog_loader();
@@ -9325,7 +9853,7 @@ var init_builtin = __esm({
9325
9853
  init_openai();
9326
9854
  init_openrouter();
9327
9855
  init_vertex();
9328
- registered2 = false;
9856
+ registered3 = false;
9329
9857
  }
9330
9858
  });
9331
9859
 
@@ -9570,7 +10098,9 @@ function toAnthropicWireMessage(message) {
9570
10098
  return {
9571
10099
  type: "tool_result",
9572
10100
  tool_use_id: part.toolUseId,
9573
- content: part.content,
10101
+ // SE7 — this wire is block-capable: strings pass through, structured
10102
+ // text/image blocks are forwarded natively.
10103
+ content: toBlockToolResultContent(part.content),
9574
10104
  ...part.isError === true ? { is_error: true } : {}
9575
10105
  };
9576
10106
  });
@@ -9647,6 +10177,7 @@ function encodeAnthropicSystem(system) {
9647
10177
  var init_anthropic_shared = __esm({
9648
10178
  "src/internal/llm/anthropic-shared.ts"() {
9649
10179
  init_finish();
10180
+ init_tool_result_content();
9650
10181
  }
9651
10182
  });
9652
10183
 
@@ -10601,7 +11132,8 @@ function toOllamaMessages(message) {
10601
11132
  if (part.type === "tool_result") {
10602
11133
  out.push({
10603
11134
  role: "tool",
10604
- content: part.content,
11135
+ // SE7 — string-only tool role: text blocks flatten; image fails fast.
11136
+ content: toStringToolResultContent(part.content, "ollama"),
10605
11137
  tool_name: part.toolUseId
10606
11138
  });
10607
11139
  }
@@ -10642,6 +11174,7 @@ var init_ollama_native = __esm({
10642
11174
  "src/internal/llm/ollama-native.ts"() {
10643
11175
  init_ollama2();
10644
11176
  init_finish();
11177
+ init_tool_result_content();
10645
11178
  OllamaNativeClient = class {
10646
11179
  constructor(options) {
10647
11180
  this.options = options;
@@ -11006,7 +11539,9 @@ function userOrToolMessages(message) {
11006
11539
  out.push({
11007
11540
  role: "tool",
11008
11541
  tool_call_id: part.toolUseId,
11009
- content: part.content
11542
+ // SE7 — this wire's tool role is string-only: text blocks flatten; an
11543
+ // image block fails fast (ConfigurationError).
11544
+ content: toStringToolResultContent(part.content, "openai")
11010
11545
  });
11011
11546
  }
11012
11547
  }
@@ -11037,6 +11572,7 @@ var init_openai2 = __esm({
11037
11572
  init_finish();
11038
11573
  init_hermes_tool_extract();
11039
11574
  init_sse();
11575
+ init_tool_result_content();
11040
11576
  OpenAIClient = class {
11041
11577
  constructor(options) {
11042
11578
  this.options = options;
@@ -12276,18 +12812,20 @@ var init_personality_filter = __esm({
12276
12812
  function createRealLocalRun(options) {
12277
12813
  const { userText, id, startTime } = prepareRunContext(options.message);
12278
12814
  const supported = /* @__PURE__ */ new Set(["stream", "wait", "cancel", "conversation"]);
12279
- const unusedFixtureScript = {
12815
+ const runScript = {
12280
12816
  events: [],
12281
12817
  finalStatus: "running",
12282
12818
  cancellable: false,
12283
- conversation: []
12819
+ conversation: [],
12820
+ // SE3 — carry the turn's provenance so buildResult forwards it onto RunResult.origin.
12821
+ ...options.sendOptions.origin !== void 0 ? { origin: options.sendOptions.origin } : {}
12284
12822
  };
12285
12823
  const handle = new RealLocalRun(
12286
12824
  {
12287
12825
  id,
12288
12826
  agentId: options.agentId,
12289
12827
  model: options.model,
12290
- script: unusedFixtureScript,
12828
+ script: runScript,
12291
12829
  supportedOps: supported,
12292
12830
  startTime
12293
12831
  },
@@ -12398,6 +12936,8 @@ function buildLoopInputs(options, runId, userText) {
12398
12936
  // M7 — forward SendOptions.context to the loop so every tool handler receives
12399
12937
  // it on `ctx.context` (shared run config set once, e.g. projectRoot).
12400
12938
  ...options.sendOptions.context !== void 0 ? { context: options.sendOptions.context } : {},
12939
+ // SE2 — forward the opt-in typed runtime-event sink to the loop.
12940
+ ...options.sendOptions.onRunEvent !== void 0 ? { runEventSink: options.sendOptions.onRunEvent } : {},
12401
12941
  // #58 / #57 — forward the per-tool timeout + tool-result guard so a consumer
12402
12942
  // can enable them via SendOptions (not only internal AgentLoopInputs).
12403
12943
  ...options.sendOptions.perToolTimeoutMs !== void 0 ? { perToolTimeoutMs: options.sendOptions.perToolTimeoutMs } : {},
@@ -15458,39 +15998,16 @@ Goal: ${ctx.goal}
15458
15998
  Subgoals: ${subgoals}
15459
15999
  Last agent response: ${ctx.lastResponse}
15460
16000
 
15461
- Respond with EXACTLY one of:
15462
- - DONE: <reason>
15463
- - CONTINUE: <what's left>
15464
- - SKIPPED: <why not applicable>
15465
-
15466
- Be strict. If unclear, prefer CONTINUE.`;
15467
- }
15468
- var init_judge_call = __esm({
15469
- "src/internal/judge/judge-call.ts"() {
15470
- init_parse_verdict();
15471
- }
15472
- });
15473
-
15474
- // src/internal/runtime/registry/agent-factory-registry.ts
15475
- var agent_factory_registry_exports = {};
15476
- __export(agent_factory_registry_exports, {
15477
- getAgentFacade: () => getAgentFacade,
15478
- setAgentFacade: () => setAgentFacade
15479
- });
15480
- function setAgentFacade(facade) {
15481
- registered3 = facade;
15482
- }
15483
- function getAgentFacade() {
15484
- if (registered3 === void 0) {
15485
- throw new Error(
15486
- "internal: Agent facade not registered. The `agent.ts` module must be loaded before internal subsystems (LocalAgent.runUntil/fork, eval, scorers, cron) invoke it."
15487
- );
15488
- }
15489
- return registered3;
16001
+ Respond with EXACTLY one of:
16002
+ - DONE: <reason>
16003
+ - CONTINUE: <what's left>
16004
+ - SKIPPED: <why not applicable>
16005
+
16006
+ Be strict. If unclear, prefer CONTINUE.`;
15490
16007
  }
15491
- var registered3;
15492
- var init_agent_factory_registry = __esm({
15493
- "src/internal/runtime/registry/agent-factory-registry.ts"() {
16008
+ var init_judge_call = __esm({
16009
+ "src/internal/judge/judge-call.ts"() {
16010
+ init_parse_verdict();
15494
16011
  }
15495
16012
  });
15496
16013
 
@@ -15658,14 +16175,14 @@ async function forkAgentImpl(parent, options, deps) {
15658
16175
  return {
15659
16176
  result: result.result,
15660
16177
  toolCalls: [],
15661
- usage: extractUsage(result)
16178
+ usage: extractUsage2(result)
15662
16179
  };
15663
16180
  });
15664
16181
  } finally {
15665
16182
  await fork.dispose();
15666
16183
  }
15667
16184
  }
15668
- function extractUsage(result) {
16185
+ function extractUsage2(result) {
15669
16186
  if (typeof result !== "object" || result === null) {
15670
16187
  return { inputTokens: 0, outputTokens: 0 };
15671
16188
  }
@@ -15824,7 +16341,7 @@ var init_local_agent_memory_hooks = __esm({
15824
16341
  async function executeSendLocked(inputs, message, options) {
15825
16342
  if (inputs.disposed) throw new AgentDisposedError(inputs.agentId);
15826
16343
  await consumePending(inputs.agentId, inputs.invalidationPending, inputs.clearInvalidation, inputs.reload);
15827
- inputs.applyModelOverride(options.model);
16344
+ inputs.applyModelOverride(normalizeModel(options.model));
15828
16345
  const userText = typeof message === "string" ? message : message.text;
15829
16346
  if (inputs.options.onBeforeSend !== void 0) {
15830
16347
  await inputs.options.onBeforeSend({
@@ -15893,6 +16410,7 @@ var init_local_agent_send = __esm({
15893
16410
  init_abort_utils();
15894
16411
  init_memory_path_selector();
15895
16412
  init_memory_store();
16413
+ init_model_selection();
15896
16414
  init_agent_session();
15897
16415
  init_safe_call();
15898
16416
  init_local_agent_invalidate();
@@ -16472,6 +16990,7 @@ function includesSetting(options, source) {
16472
16990
  var LocalAgent;
16473
16991
  var init_local_agent = __esm({
16474
16992
  "src/internal/runtime/local-agent/local-agent.ts"() {
16993
+ init_agent_generate();
16475
16994
  init_errors();
16476
16995
  init_ids();
16477
16996
  init_cwd_mutex();
@@ -16482,6 +17001,7 @@ var init_local_agent = __esm({
16482
17001
  init_hooks_executor();
16483
17002
  init_post_run_lifecycle();
16484
17003
  init_memory_path_selector();
17004
+ init_model_selection();
16485
17005
  init_agent_registry();
16486
17006
  init_live_agent_registry();
16487
17007
  init_agent_session();
@@ -16558,7 +17078,7 @@ var init_local_agent = __esm({
16558
17078
  constructor(options) {
16559
17079
  this.agentId = options.agentId ?? generateLocalAgentId();
16560
17080
  this._telemetry = createTelemetry(options.telemetry);
16561
- this.model = options.model;
17081
+ this.model = normalizeModel(options.model);
16562
17082
  this.options = options;
16563
17083
  this.workspaceCwd = resolveCwd(options.local?.cwd);
16564
17084
  this.conversationStorage = options.conversationStorage;
@@ -16625,6 +17145,11 @@ var init_local_agent = __esm({
16625
17145
  hooks() {
16626
17146
  return this.hooksExecutor;
16627
17147
  }
17148
+ // SE9 — integrated structured output; delegates to the shared helper.
17149
+ generate(message, options) {
17150
+ const { apiKey, local } = this.options;
17151
+ return agentGenerate(this, this.model, apiKey, local, message, options);
17152
+ }
16628
17153
  async send(message, options = {}) {
16629
17154
  if (options.tools !== void 0 && options.tools.length > 0) {
16630
17155
  validateToolCatalog(options.tools);
@@ -16857,6 +17382,7 @@ var init_local_agent = __esm({
16857
17382
  }
16858
17383
  });
16859
17384
  async function runCreateUnderSpan(options, span) {
17385
+ options = { ...options, model: normalizeModel(options.model) };
16860
17386
  validateAgentOptions(options);
16861
17387
  validateCloudToolParity(options);
16862
17388
  await guardAgainstIdCollision(options);
@@ -16930,7 +17456,10 @@ async function createLocalAgent(options) {
16930
17456
  const willFlowToProvider = !isFixtureApiKey(apiKey) && !shouldUseRealLocalRuntime(apiKey);
16931
17457
  const shape = validateApiKeyShape(apiKey, {
16932
17458
  strict: willFlowToProvider,
16933
- ...willFlowToProvider ? { provider: providerFromModelId(options.model?.id) } : {}
17459
+ // `options.model` is already normalized by `runCreateUnderSpan`; `normalizeModel`
17460
+ // here is the idempotent narrowing of the widened public type (`{id}` passes
17461
+ // through by reference) — cleaner than an `as` cast.
17462
+ ...willFlowToProvider ? { provider: providerFromModelId(normalizeModel(options.model)?.id) } : {}
16934
17463
  });
16935
17464
  if (shape.malformed) {
16936
17465
  throw new AuthenticationError(shape.message, { code: "malformed_api_key" });
@@ -16996,6 +17525,10 @@ async function rehydrateExistingAgent(agentId, existing, options) {
16996
17525
  ...existing.options,
16997
17526
  ...options,
16998
17527
  ...mergedLocal !== void 0 ? { local: mergedLocal } : {},
17528
+ // SE8 — normalize a caller-supplied bare-string model override at this resume
17529
+ // boundary (Agent.resume never flows through runCreateUnderSpan). Cloud resume
17530
+ // honors it; local resume forces the persisted model below.
17531
+ model: normalizeModel(options.model ?? existing.options.model),
16999
17532
  mcpServers: void 0,
17000
17533
  agentId
17001
17534
  };
@@ -17078,237 +17611,11 @@ var init_agent_helpers = __esm({
17078
17611
  init_cloud_agent();
17079
17612
  init_cloud_tool_parity();
17080
17613
  init_local_agent();
17614
+ init_model_selection();
17081
17615
  init_agent_registry();
17082
17616
  init_validate_agent_options();
17083
17617
  }
17084
17618
  });
17085
- function toJsonSchema(schema, options = { unrepresentable: "any" }) {
17086
- return toJSONSchema(schema, options);
17087
- }
17088
- var init_to_json_schema = __esm({
17089
- "src/internal/zod/to-json-schema.ts"() {
17090
- }
17091
- });
17092
- function requireZod() {
17093
- if (cachedZ !== void 0) return cachedZ;
17094
- const r = createRequire(import.meta.url);
17095
- let mod;
17096
- try {
17097
- mod = r("zod");
17098
- } catch (cause) {
17099
- throw new ConfigurationError(
17100
- 'Structured output requires the optional peer dependency `zod`. Add `"zod": "^3.25.0 || ^4.0.0"` to your package.json and reinstall.',
17101
- { code: "zod_not_installed", cause }
17102
- );
17103
- }
17104
- cachedZ = mod.z ?? mod;
17105
- return cachedZ;
17106
- }
17107
- function makeOutputTool(jsonSchema, onCapture) {
17108
- return {
17109
- name: "output",
17110
- description: "Call this tool with your final structured answer. Match the JSON schema exactly.",
17111
- inputSchema: jsonSchema,
17112
- handler: (input) => {
17113
- const out = onCapture(input);
17114
- if (typeof out === "string") return out;
17115
- if (out instanceof Promise) return out;
17116
- return "";
17117
- }
17118
- };
17119
- }
17120
- function buildTransientAgentOptions(params) {
17121
- return {
17122
- model: params.model,
17123
- local: params.local,
17124
- tools: [params.outputTool],
17125
- systemPrompt: params.systemPrompt ?? "You produce structured output by calling the `output` tool exactly once. Match the JSON schema.",
17126
- ...params.apiKey !== void 0 ? { apiKey: params.apiKey } : {},
17127
- ...params.providers !== void 0 ? { providers: params.providers } : {}
17128
- };
17129
- }
17130
- function extractUsage2(result) {
17131
- const u = result.usage;
17132
- if (u === void 0) return { inputTokens: 0, outputTokens: 0 };
17133
- return { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 };
17134
- }
17135
- function buildToolPrompt(prompt) {
17136
- return `${prompt}
17137
-
17138
- Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
17139
- }
17140
- function setupStructuredOutput(schema, maxRetries) {
17141
- const z7 = requireZod();
17142
- const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
17143
- return {
17144
- z: z7,
17145
- jsonSchema,
17146
- maxRetries: maxRetries ?? 1,
17147
- initialUsage: { inputTokens: 0, outputTokens: 0 }
17148
- };
17149
- }
17150
- async function disposeAndDeleteTransient(agent, deletor) {
17151
- await agent.dispose();
17152
- try {
17153
- await deletor(agent.agentId);
17154
- } catch {
17155
- }
17156
- }
17157
- var cachedZ;
17158
- var init_structured_output_helpers = __esm({
17159
- "src/internal/structured-output-helpers.ts"() {
17160
- init_errors();
17161
- init_to_json_schema();
17162
- }
17163
- });
17164
-
17165
- // src/generate-object.ts
17166
- var generate_object_exports = {};
17167
- __export(generate_object_exports, {
17168
- GenerateObjectError: () => GenerateObjectError,
17169
- generateObjectImpl: () => generateObjectImpl
17170
- });
17171
- function salvagePartial(schema, raw) {
17172
- if (typeof raw !== "object" || raw === null) return raw;
17173
- const shape = schema.shape;
17174
- if (shape === void 0 || typeof shape !== "object") return raw;
17175
- const rawObj = raw;
17176
- const out = {};
17177
- for (const [key, fieldSchema] of Object.entries(shape)) {
17178
- if (typeof fieldSchema?.safeParse !== "function") continue;
17179
- const parsed = fieldSchema.safeParse(rawObj[key]);
17180
- if (parsed.success) out[key] = parsed.data;
17181
- }
17182
- return out;
17183
- }
17184
- async function runReasoningPhase(options, deps) {
17185
- const reasoningOptions = {
17186
- model: options.model,
17187
- local: options.local,
17188
- ...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
17189
- ...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
17190
- ...options.providers !== void 0 ? { providers: options.providers } : {}
17191
- };
17192
- const reasoningAgent = await deps.create(reasoningOptions);
17193
- try {
17194
- const run = await reasoningAgent.send(options.prompt);
17195
- const result = await run.wait();
17196
- const text = result.result;
17197
- return typeof text === "string" ? text : options.prompt;
17198
- } finally {
17199
- await disposeAndDeleteTransient(reasoningAgent, deps.delete);
17200
- }
17201
- }
17202
- async function generateObjectImpl(options, deps) {
17203
- const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(
17204
- options.schema,
17205
- options.maxRetries
17206
- );
17207
- let capturedRaw;
17208
- let lastUsage = initialUsage;
17209
- const sentinel = /* @__PURE__ */ Symbol("generate-object-sentinel");
17210
- class CaptureSentinel extends Error {
17211
- constructor(captured) {
17212
- super("generate-object-capture");
17213
- this.captured = captured;
17214
- }
17215
- captured;
17216
- [sentinel] = true;
17217
- }
17218
- const outputTool = makeOutputTool(jsonSchema, (input) => {
17219
- if (capturedRaw === void 0) {
17220
- capturedRaw = input;
17221
- }
17222
- throw new CaptureSentinel(input);
17223
- });
17224
- const reasoningText = options.structuringModel !== void 0 ? await runReasoningPhase(options, deps) : void 0;
17225
- const structuringModel = options.structuringModel ?? options.model;
17226
- const structuringPrompt = reasoningText ?? options.prompt;
17227
- const agentOptions = buildTransientAgentOptions({
17228
- model: structuringModel,
17229
- local: options.local,
17230
- outputTool,
17231
- ...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
17232
- ...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
17233
- ...options.providers !== void 0 ? { providers: options.providers } : {}
17234
- });
17235
- const agent = await deps.create(agentOptions);
17236
- try {
17237
- const userMessage = buildToolPrompt(structuringPrompt);
17238
- let lastParseError;
17239
- for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
17240
- capturedRaw = void 0;
17241
- const run = await agent.send(userMessage);
17242
- const result = await run.wait();
17243
- lastUsage = extractUsage2(result);
17244
- if (capturedRaw === void 0) {
17245
- if (result.status === "error" && result.error !== void 0) {
17246
- throw new GenerateObjectError(
17247
- "no_tool_call",
17248
- `Agent run failed before the model could reply: ${result.error.message ?? "unknown error"} [${result.error.code ?? "?"}]`,
17249
- result.error
17250
- );
17251
- }
17252
- if (attempt === maxRetries) {
17253
- throw new GenerateObjectError(
17254
- "no_tool_call",
17255
- "The model returned text instead of calling the `output` tool."
17256
- );
17257
- }
17258
- continue;
17259
- }
17260
- const parsed = options.schema.safeParse(capturedRaw);
17261
- if (parsed.success) {
17262
- return {
17263
- object: parsed.data,
17264
- raw: capturedRaw,
17265
- usage: lastUsage,
17266
- finishReason: "tool_use"
17267
- };
17268
- }
17269
- lastParseError = parsed.error;
17270
- }
17271
- if (options.errorStrategy === "return-raw") {
17272
- return {
17273
- object: capturedRaw,
17274
- raw: capturedRaw,
17275
- usage: lastUsage,
17276
- finishReason: "tool_use"
17277
- };
17278
- }
17279
- if (options.errorStrategy === "return-partial") {
17280
- return {
17281
- object: salvagePartial(options.schema, capturedRaw),
17282
- raw: capturedRaw,
17283
- usage: lastUsage,
17284
- finishReason: "tool_use"
17285
- };
17286
- }
17287
- throw new GenerateObjectError(
17288
- "parse_failed",
17289
- "Schema parse failed after all retries.",
17290
- lastParseError
17291
- );
17292
- } finally {
17293
- await disposeAndDeleteTransient(agent, deps.delete);
17294
- }
17295
- }
17296
- var GenerateObjectError;
17297
- var init_generate_object = __esm({
17298
- "src/generate-object.ts"() {
17299
- init_structured_output_helpers();
17300
- GenerateObjectError = class extends Error {
17301
- name = "GenerateObjectError";
17302
- code;
17303
- cause;
17304
- constructor(code, message, cause) {
17305
- super(message);
17306
- this.code = code;
17307
- if (cause !== void 0) this.cause = cause;
17308
- }
17309
- };
17310
- }
17311
- });
17312
17619
 
17313
17620
  // src/stream-object.ts
17314
17621
  var stream_object_exports = {};
@@ -17364,7 +17671,7 @@ async function* streamObjectImpl(options, deps) {
17364
17671
  }
17365
17672
  }
17366
17673
  const result = await run.wait();
17367
- lastUsage = extractUsage2(result);
17674
+ lastUsage = extractUsage(result);
17368
17675
  if (capturedRaw === void 0) {
17369
17676
  if (result.status === "error" && result.error !== void 0) {
17370
17677
  throw new StreamObjectError(
@@ -18011,6 +18318,7 @@ var init_agent = __esm({
18011
18318
  };
18012
18319
  setAgentFacade({
18013
18320
  create: (options) => Agent.create(options),
18321
+ delete: (agentId) => Agent.delete(agentId),
18014
18322
  prompt: (message, options) => Agent.prompt(message, options),
18015
18323
  get: (agentId) => Agent.get(agentId),
18016
18324
  resume: (agentId, options) => Agent.resume(agentId, options),
@@ -18067,7 +18375,9 @@ var MessageBus = class {
18067
18375
  ...partial,
18068
18376
  from,
18069
18377
  to,
18070
- timestamp: Date.now()
18378
+ timestamp: Date.now(),
18379
+ // SE3 — provenance projection of the sender address (thin view over `from`).
18380
+ origin: { kind: "peer", from }
18071
18381
  };
18072
18382
  handler(message);
18073
18383
  }
@@ -18081,7 +18391,9 @@ var MessageBus = class {
18081
18391
  ...partial,
18082
18392
  from,
18083
18393
  to,
18084
- timestamp: Date.now()
18394
+ timestamp: Date.now(),
18395
+ // SE3 — provenance projection of the sender address (thin view over `from`).
18396
+ origin: { kind: "peer", from }
18085
18397
  };
18086
18398
  return Promise.race([
18087
18399
  Promise.resolve(handler(message)),
@@ -18111,6 +18423,52 @@ var MaxDelegationDepthError = class extends Error {
18111
18423
  maxDepth;
18112
18424
  code = "max_delegation_depth";
18113
18425
  };
18426
+ async function applyDelegationStart(spec, input) {
18427
+ if (spec.onDelegationStart === void 0) return { input };
18428
+ const decision = await spec.onDelegationStart({ input, name: spec.name });
18429
+ if (decision === void 0) return { input };
18430
+ if (decision.proceed === false)
18431
+ return { reject: decision.rejectionReason ?? "(delegation rejected)" };
18432
+ return { input: decision.modifiedInput ?? input };
18433
+ }
18434
+ async function runChildAgent(spec, input, signal) {
18435
+ const { Agent: Agent2 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
18436
+ const agent = await Agent2.create({
18437
+ ...spec.model ? { model: { id: spec.model } } : {},
18438
+ systemPrompt: spec.instructions,
18439
+ tools: spec.tools ?? []
18440
+ });
18441
+ try {
18442
+ const run = signal !== void 0 ? await agent.send(input, { signal }) : await agent.send(input);
18443
+ const result = await run.wait();
18444
+ return result.result ?? "(no response)";
18445
+ } finally {
18446
+ agent.dispose();
18447
+ }
18448
+ }
18449
+ async function notifyDelegationError(spec, input, error) {
18450
+ if (spec.onDelegationComplete === void 0) return;
18451
+ try {
18452
+ await spec.onDelegationComplete({ input, name: spec.name, error });
18453
+ } catch {
18454
+ }
18455
+ }
18456
+ function applyMessageFilter(spec, input, messages) {
18457
+ if (spec.messageFilter === void 0 || messages === void 0) return input;
18458
+ const filtered = spec.messageFilter({ messages, input, name: spec.name });
18459
+ if (filtered.length === 0) return input;
18460
+ const preamble = filtered.map((m) => `${m.role}: ${m.content}`).join("\n");
18461
+ return `Prior conversation:
18462
+ ${preamble}
18463
+
18464
+ Task:
18465
+ ${input}`;
18466
+ }
18467
+ async function applyDelegationComplete(spec, input, result) {
18468
+ if (spec.onDelegationComplete === void 0) return result;
18469
+ const completion = await spec.onDelegationComplete({ input, name: spec.name, result });
18470
+ return completion?.feedback !== void 0 ? result + completion.feedback : result;
18471
+ }
18114
18472
  function defineSubAgent(spec, _parentDepth = 0) {
18115
18473
  const currentDepth = _parentDepth + 1;
18116
18474
  const maxDepth = spec.maxDelegationDepth ?? 3;
@@ -18124,21 +18482,19 @@ function defineSubAgent(spec, _parentDepth = 0) {
18124
18482
  name: spec.name,
18125
18483
  description: spec.description,
18126
18484
  inputSchema,
18127
- handler: async (rawInput) => {
18128
- const { input } = inputSchema.parse(rawInput);
18129
- const { Agent: Agent2 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
18130
- const agent = await Agent2.create({
18131
- ...spec.model ? { model: { id: spec.model } } : {},
18132
- systemPrompt: spec.instructions,
18133
- tools: spec.tools ?? []
18134
- });
18485
+ handler: async (rawInput, ctx) => {
18486
+ const { input: parsed } = inputSchema.parse(rawInput);
18487
+ const start = await applyDelegationStart(spec, parsed);
18488
+ if ("reject" in start) return start.reject;
18489
+ const input = applyMessageFilter(spec, start.input, ctx?.messages);
18490
+ let result;
18135
18491
  try {
18136
- const run = await agent.send(input);
18137
- const result = await run.wait();
18138
- return result.result ?? "(no response)";
18139
- } finally {
18140
- agent.dispose();
18492
+ result = await runChildAgent(spec, input, ctx?.signal);
18493
+ } catch (error) {
18494
+ await notifyDelegationError(spec, input, error);
18495
+ throw error;
18141
18496
  }
18497
+ return applyDelegationComplete(spec, input, result);
18142
18498
  }
18143
18499
  };
18144
18500
  }