@theokit/sdk 2.20.0 → 2.21.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 (88) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/dist/a2a/index.cjs +592 -290
  3. package/dist/a2a/index.cjs.map +1 -1
  4. package/dist/a2a/index.js +593 -291
  5. package/dist/a2a/index.js.map +1 -1
  6. package/dist/a2a/types.d.cts +7 -0
  7. package/dist/a2a/types.d.ts +7 -0
  8. package/dist/agent-builder.d.ts +2 -1
  9. package/dist/agent-generate.d.ts +12 -0
  10. package/dist/client/index.cjs.map +1 -1
  11. package/dist/client/index.d.cts +5 -0
  12. package/dist/client/index.d.ts +5 -0
  13. package/dist/client/index.js.map +1 -1
  14. package/dist/client/theokit-client.d.cts +6 -0
  15. package/dist/client/theokit-client.d.ts +6 -0
  16. package/dist/client/types.d.cts +2 -0
  17. package/dist/client/types.d.ts +2 -0
  18. package/dist/{cron-D2yLOrk2.d.ts → cron-YrmsszEN.d.cts} +53 -3
  19. package/dist/{cron-B8fqui49.d.cts → cron-dpvtRoro.d.ts} +53 -3
  20. package/dist/cron.cjs +642 -387
  21. package/dist/cron.cjs.map +1 -1
  22. package/dist/cron.d.cts +3 -2
  23. package/dist/cron.d.ts +3 -2
  24. package/dist/cron.js +643 -388
  25. package/dist/cron.js.map +1 -1
  26. package/dist/{errors-5lj1EWgs.d.ts → errors-C4vZPqXf.d.ts} +2 -2
  27. package/dist/{errors-CE-lMBi2.d.cts → errors-DrcpYVfZ.d.cts} +2 -2
  28. package/dist/errors.d.cts +3 -2
  29. package/dist/eval.cjs +642 -387
  30. package/dist/eval.cjs.map +1 -1
  31. package/dist/eval.js +642 -387
  32. package/dist/eval.js.map +1 -1
  33. package/dist/generate-object.d.ts +4 -3
  34. package/dist/index.cjs +788 -390
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +259 -17
  37. package/dist/index.d.ts +259 -17
  38. package/dist/index.js +786 -392
  39. package/dist/index.js.map +1 -1
  40. package/dist/internal/agent-loop/loop-types.d.ts +2 -0
  41. package/dist/internal/agent-loop/tool-result-guard.d.ts +1 -0
  42. package/dist/internal/llm/tool-result-content.d.ts +40 -0
  43. package/dist/internal/llm/types.d.ts +6 -1
  44. package/dist/internal/persistence/conversation-storage-fs.d.cts +3 -1
  45. package/dist/internal/persistence/conversation-storage-fs.d.ts +3 -1
  46. package/dist/internal/persistence/conversation-storage-memory.d.cts +3 -1
  47. package/dist/internal/persistence/conversation-storage-memory.d.ts +3 -1
  48. package/dist/internal/persistence/session-meta.d.cts +13 -0
  49. package/dist/internal/persistence/session-meta.d.ts +13 -0
  50. package/dist/internal/runtime/model-selection.d.ts +14 -0
  51. package/dist/internal/structured-output-helpers.d.ts +1 -1
  52. package/dist/permission-engine.d.ts +32 -1
  53. package/dist/{run-BgfBWX-z.d.cts → run-BMo8yRwK.d.cts} +262 -19
  54. package/dist/{run-BgfBWX-z.d.ts → run-BMo8yRwK.d.ts} +262 -19
  55. package/dist/stream-object.d.ts +2 -1
  56. package/dist/tool-error.d.ts +30 -0
  57. package/dist/types/agent-prims.d.ts +10 -8
  58. package/dist/types/agent.d.ts +12 -1
  59. package/dist/types/content-blocks.d.ts +47 -0
  60. package/dist/types/conversation-storage.d.ts +38 -0
  61. package/dist/types/index.d.ts +1 -0
  62. package/dist/types/messages.d.ts +2 -9
  63. package/dist/types/run-events.d.ts +84 -0
  64. package/dist/types/run.d.ts +115 -1
  65. package/dist/types/session.d.ts +99 -0
  66. package/dist/types/workflow.d.ts +7 -0
  67. package/dist/workflow.cjs +7 -2
  68. package/dist/workflow.cjs.map +1 -1
  69. package/dist/workflow.d.cts +2 -0
  70. package/dist/workflow.d.ts +2 -0
  71. package/dist/workflow.js +7 -2
  72. package/dist/workflow.js.map +1 -1
  73. package/package.json +14 -34
  74. package/dist/internal/observability/context.d.cts +0 -23
  75. package/dist/internal/observability/context.d.ts +0 -23
  76. package/dist/internal/observability/index.cjs +0 -38
  77. package/dist/internal/observability/index.cjs.map +0 -1
  78. package/dist/internal/observability/index.d.cts +0 -8
  79. package/dist/internal/observability/index.d.ts +0 -8
  80. package/dist/internal/observability/index.js +0 -33
  81. package/dist/internal/observability/index.js.map +0 -1
  82. package/dist/internal/plugins/index.cjs +0 -363
  83. package/dist/internal/plugins/index.cjs.map +0 -1
  84. package/dist/internal/plugins/index.js +0 -357
  85. package/dist/internal/plugins/index.js.map +0 -1
  86. package/dist/internal/workflow/index.d.ts +0 -12
  87. package/dist/server/adapter/index.d.cts +0 -8
  88. 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)) {
@@ -7893,9 +8340,13 @@ async function runHandlerTool(kind, handler, call, signal, context) {
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 });
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 = [
@@ -9301,8 +9819,8 @@ var init_vertex = __esm({
9301
9819
 
9302
9820
  // src/internal/providers/builtin/index.ts
9303
9821
  function registerBuiltins() {
9304
- if (registered2) return;
9305
- registered2 = true;
9822
+ if (registered3) return;
9823
+ registered3 = true;
9306
9824
  registerProvider(ANTHROPIC);
9307
9825
  registerProvider(OPENAI);
9308
9826
  registerProvider(OPENROUTER);
@@ -9314,7 +9832,7 @@ function registerBuiltins() {
9314
9832
  registerProvider(VERTEX);
9315
9833
  registerCatalogProviders();
9316
9834
  }
9317
- var registered2;
9835
+ var registered3;
9318
9836
  var init_builtin = __esm({
9319
9837
  "src/internal/providers/builtin/index.ts"() {
9320
9838
  init_catalog_loader();
@@ -9328,7 +9846,7 @@ var init_builtin = __esm({
9328
9846
  init_openai();
9329
9847
  init_openrouter();
9330
9848
  init_vertex();
9331
- registered2 = false;
9849
+ registered3 = false;
9332
9850
  }
9333
9851
  });
9334
9852
 
@@ -9573,7 +10091,9 @@ function toAnthropicWireMessage(message) {
9573
10091
  return {
9574
10092
  type: "tool_result",
9575
10093
  tool_use_id: part.toolUseId,
9576
- content: part.content,
10094
+ // SE7 — this wire is block-capable: strings pass through, structured
10095
+ // text/image blocks are forwarded natively.
10096
+ content: toBlockToolResultContent(part.content),
9577
10097
  ...part.isError === true ? { is_error: true } : {}
9578
10098
  };
9579
10099
  });
@@ -9650,6 +10170,7 @@ function encodeAnthropicSystem(system) {
9650
10170
  var init_anthropic_shared = __esm({
9651
10171
  "src/internal/llm/anthropic-shared.ts"() {
9652
10172
  init_finish();
10173
+ init_tool_result_content();
9653
10174
  }
9654
10175
  });
9655
10176
 
@@ -10604,7 +11125,8 @@ function toOllamaMessages(message) {
10604
11125
  if (part.type === "tool_result") {
10605
11126
  out.push({
10606
11127
  role: "tool",
10607
- content: part.content,
11128
+ // SE7 — string-only tool role: text blocks flatten; image fails fast.
11129
+ content: toStringToolResultContent(part.content, "ollama"),
10608
11130
  tool_name: part.toolUseId
10609
11131
  });
10610
11132
  }
@@ -10645,6 +11167,7 @@ var init_ollama_native = __esm({
10645
11167
  "src/internal/llm/ollama-native.ts"() {
10646
11168
  init_ollama2();
10647
11169
  init_finish();
11170
+ init_tool_result_content();
10648
11171
  OllamaNativeClient = class {
10649
11172
  constructor(options) {
10650
11173
  this.options = options;
@@ -11009,7 +11532,9 @@ function userOrToolMessages(message) {
11009
11532
  out.push({
11010
11533
  role: "tool",
11011
11534
  tool_call_id: part.toolUseId,
11012
- content: part.content
11535
+ // SE7 — this wire's tool role is string-only: text blocks flatten; an
11536
+ // image block fails fast (ConfigurationError).
11537
+ content: toStringToolResultContent(part.content, "openai")
11013
11538
  });
11014
11539
  }
11015
11540
  }
@@ -11040,6 +11565,7 @@ var init_openai2 = __esm({
11040
11565
  init_finish();
11041
11566
  init_hermes_tool_extract();
11042
11567
  init_sse();
11568
+ init_tool_result_content();
11043
11569
  OpenAIClient = class {
11044
11570
  constructor(options) {
11045
11571
  this.options = options;
@@ -12279,18 +12805,20 @@ var init_personality_filter = __esm({
12279
12805
  function createRealLocalRun(options) {
12280
12806
  const { userText, id, startTime } = prepareRunContext(options.message);
12281
12807
  const supported = /* @__PURE__ */ new Set(["stream", "wait", "cancel", "conversation"]);
12282
- const unusedFixtureScript = {
12808
+ const runScript = {
12283
12809
  events: [],
12284
12810
  finalStatus: "running",
12285
12811
  cancellable: false,
12286
- conversation: []
12812
+ conversation: [],
12813
+ // SE3 — carry the turn's provenance so buildResult forwards it onto RunResult.origin.
12814
+ ...options.sendOptions.origin !== void 0 ? { origin: options.sendOptions.origin } : {}
12287
12815
  };
12288
12816
  const handle = new RealLocalRun(
12289
12817
  {
12290
12818
  id,
12291
12819
  agentId: options.agentId,
12292
12820
  model: options.model,
12293
- script: unusedFixtureScript,
12821
+ script: runScript,
12294
12822
  supportedOps: supported,
12295
12823
  startTime
12296
12824
  },
@@ -12401,6 +12929,8 @@ function buildLoopInputs(options, runId, userText) {
12401
12929
  // M7 — forward SendOptions.context to the loop so every tool handler receives
12402
12930
  // it on `ctx.context` (shared run config set once, e.g. projectRoot).
12403
12931
  ...options.sendOptions.context !== void 0 ? { context: options.sendOptions.context } : {},
12932
+ // SE2 — forward the opt-in typed runtime-event sink to the loop.
12933
+ ...options.sendOptions.onRunEvent !== void 0 ? { runEventSink: options.sendOptions.onRunEvent } : {},
12404
12934
  // #58 / #57 — forward the per-tool timeout + tool-result guard so a consumer
12405
12935
  // can enable them via SendOptions (not only internal AgentLoopInputs).
12406
12936
  ...options.sendOptions.perToolTimeoutMs !== void 0 ? { perToolTimeoutMs: options.sendOptions.perToolTimeoutMs } : {},
@@ -15474,29 +16004,6 @@ var init_judge_call = __esm({
15474
16004
  }
15475
16005
  });
15476
16006
 
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;
15493
- }
15494
- var registered3;
15495
- var init_agent_factory_registry = __esm({
15496
- "src/internal/runtime/registry/agent-factory-registry.ts"() {
15497
- }
15498
- });
15499
-
15500
16007
  // src/internal/runtime/lifecycle/run-to-completion.ts
15501
16008
  var run_to_completion_exports = {};
15502
16009
  __export(run_to_completion_exports, {
@@ -15661,14 +16168,14 @@ async function forkAgentImpl(parent, options, deps) {
15661
16168
  return {
15662
16169
  result: result.result,
15663
16170
  toolCalls: [],
15664
- usage: extractUsage(result)
16171
+ usage: extractUsage2(result)
15665
16172
  };
15666
16173
  });
15667
16174
  } finally {
15668
16175
  await fork.dispose();
15669
16176
  }
15670
16177
  }
15671
- function extractUsage(result) {
16178
+ function extractUsage2(result) {
15672
16179
  if (typeof result !== "object" || result === null) {
15673
16180
  return { inputTokens: 0, outputTokens: 0 };
15674
16181
  }
@@ -15827,7 +16334,7 @@ var init_local_agent_memory_hooks = __esm({
15827
16334
  async function executeSendLocked(inputs, message, options) {
15828
16335
  if (inputs.disposed) throw new AgentDisposedError(inputs.agentId);
15829
16336
  await consumePending(inputs.agentId, inputs.invalidationPending, inputs.clearInvalidation, inputs.reload);
15830
- inputs.applyModelOverride(options.model);
16337
+ inputs.applyModelOverride(normalizeModel(options.model));
15831
16338
  const userText = typeof message === "string" ? message : message.text;
15832
16339
  if (inputs.options.onBeforeSend !== void 0) {
15833
16340
  await inputs.options.onBeforeSend({
@@ -15896,6 +16403,7 @@ var init_local_agent_send = __esm({
15896
16403
  init_abort_utils();
15897
16404
  init_memory_path_selector();
15898
16405
  init_memory_store();
16406
+ init_model_selection();
15899
16407
  init_agent_session();
15900
16408
  init_safe_call();
15901
16409
  init_local_agent_invalidate();
@@ -16475,6 +16983,7 @@ function includesSetting(options, source) {
16475
16983
  var LocalAgent;
16476
16984
  var init_local_agent = __esm({
16477
16985
  "src/internal/runtime/local-agent/local-agent.ts"() {
16986
+ init_agent_generate();
16478
16987
  init_errors();
16479
16988
  init_ids();
16480
16989
  init_cwd_mutex();
@@ -16485,6 +16994,7 @@ var init_local_agent = __esm({
16485
16994
  init_hooks_executor();
16486
16995
  init_post_run_lifecycle();
16487
16996
  init_memory_path_selector();
16997
+ init_model_selection();
16488
16998
  init_agent_registry();
16489
16999
  init_live_agent_registry();
16490
17000
  init_agent_session();
@@ -16561,7 +17071,7 @@ var init_local_agent = __esm({
16561
17071
  constructor(options) {
16562
17072
  this.agentId = options.agentId ?? generateLocalAgentId();
16563
17073
  this._telemetry = createTelemetry(options.telemetry);
16564
- this.model = options.model;
17074
+ this.model = normalizeModel(options.model);
16565
17075
  this.options = options;
16566
17076
  this.workspaceCwd = resolveCwd(options.local?.cwd);
16567
17077
  this.conversationStorage = options.conversationStorage;
@@ -16628,6 +17138,11 @@ var init_local_agent = __esm({
16628
17138
  hooks() {
16629
17139
  return this.hooksExecutor;
16630
17140
  }
17141
+ // SE9 — integrated structured output; delegates to the shared helper.
17142
+ generate(message, options) {
17143
+ const { apiKey, local } = this.options;
17144
+ return agentGenerate(this, this.model, apiKey, local, message, options);
17145
+ }
16631
17146
  async send(message, options = {}) {
16632
17147
  if (options.tools !== void 0 && options.tools.length > 0) {
16633
17148
  validateToolCatalog(options.tools);
@@ -16860,6 +17375,7 @@ var init_local_agent = __esm({
16860
17375
  }
16861
17376
  });
16862
17377
  async function runCreateUnderSpan(options, span) {
17378
+ options = { ...options, model: normalizeModel(options.model) };
16863
17379
  validateAgentOptions(options);
16864
17380
  validateCloudToolParity(options);
16865
17381
  await guardAgainstIdCollision(options);
@@ -16933,7 +17449,10 @@ async function createLocalAgent(options) {
16933
17449
  const willFlowToProvider = !isFixtureApiKey(apiKey) && !shouldUseRealLocalRuntime(apiKey);
16934
17450
  const shape = validateApiKeyShape(apiKey, {
16935
17451
  strict: willFlowToProvider,
16936
- ...willFlowToProvider ? { provider: providerFromModelId(options.model?.id) } : {}
17452
+ // `options.model` is already normalized by `runCreateUnderSpan`; `normalizeModel`
17453
+ // here is the idempotent narrowing of the widened public type (`{id}` passes
17454
+ // through by reference) — cleaner than an `as` cast.
17455
+ ...willFlowToProvider ? { provider: providerFromModelId(normalizeModel(options.model)?.id) } : {}
16937
17456
  });
16938
17457
  if (shape.malformed) {
16939
17458
  throw new AuthenticationError(shape.message, { code: "malformed_api_key" });
@@ -16999,6 +17518,10 @@ async function rehydrateExistingAgent(agentId, existing, options) {
16999
17518
  ...existing.options,
17000
17519
  ...options,
17001
17520
  ...mergedLocal !== void 0 ? { local: mergedLocal } : {},
17521
+ // SE8 — normalize a caller-supplied bare-string model override at this resume
17522
+ // boundary (Agent.resume never flows through runCreateUnderSpan). Cloud resume
17523
+ // honors it; local resume forces the persisted model below.
17524
+ model: normalizeModel(options.model ?? existing.options.model),
17002
17525
  mcpServers: void 0,
17003
17526
  agentId
17004
17527
  };
@@ -17081,237 +17604,11 @@ var init_agent_helpers = __esm({
17081
17604
  init_cloud_agent();
17082
17605
  init_cloud_tool_parity();
17083
17606
  init_local_agent();
17607
+ init_model_selection();
17084
17608
  init_agent_registry();
17085
17609
  init_validate_agent_options();
17086
17610
  }
17087
17611
  });
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
17612
 
17316
17613
  // src/stream-object.ts
17317
17614
  var stream_object_exports = {};
@@ -17367,7 +17664,7 @@ async function* streamObjectImpl(options, deps) {
17367
17664
  }
17368
17665
  }
17369
17666
  const result = await run.wait();
17370
- lastUsage = extractUsage2(result);
17667
+ lastUsage = extractUsage(result);
17371
17668
  if (capturedRaw === void 0) {
17372
17669
  if (result.status === "error" && result.error !== void 0) {
17373
17670
  throw new StreamObjectError(
@@ -18014,6 +18311,7 @@ var init_agent = __esm({
18014
18311
  };
18015
18312
  setAgentFacade({
18016
18313
  create: (options) => Agent.create(options),
18314
+ delete: (agentId) => Agent.delete(agentId),
18017
18315
  prompt: (message, options) => Agent.prompt(message, options),
18018
18316
  get: (agentId) => Agent.get(agentId),
18019
18317
  resume: (agentId, options) => Agent.resume(agentId, options),
@@ -18070,7 +18368,9 @@ var MessageBus = class {
18070
18368
  ...partial,
18071
18369
  from,
18072
18370
  to,
18073
- timestamp: Date.now()
18371
+ timestamp: Date.now(),
18372
+ // SE3 — provenance projection of the sender address (thin view over `from`).
18373
+ origin: { kind: "peer", from }
18074
18374
  };
18075
18375
  handler(message);
18076
18376
  }
@@ -18084,7 +18384,9 @@ var MessageBus = class {
18084
18384
  ...partial,
18085
18385
  from,
18086
18386
  to,
18087
- timestamp: Date.now()
18387
+ timestamp: Date.now(),
18388
+ // SE3 — provenance projection of the sender address (thin view over `from`).
18389
+ origin: { kind: "peer", from }
18088
18390
  };
18089
18391
  return Promise.race([
18090
18392
  Promise.resolve(handler(message)),