@theokit/sdk 2.19.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 (89) hide show
  1. package/CHANGELOG.md +123 -0
  2. package/dist/a2a/index.cjs +611 -274
  3. package/dist/a2a/index.cjs.map +1 -1
  4. package/dist/a2a/index.js +612 -275
  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/create-skill.d.ts +29 -0
  19. package/dist/{cron-D_wK1S-0.d.cts → cron-YrmsszEN.d.cts} +110 -3
  20. package/dist/{cron-Cep07kTz.d.ts → cron-dpvtRoro.d.ts} +110 -3
  21. package/dist/cron.cjs +660 -370
  22. package/dist/cron.cjs.map +1 -1
  23. package/dist/cron.d.cts +3 -2
  24. package/dist/cron.d.ts +3 -2
  25. package/dist/cron.js +661 -371
  26. package/dist/cron.js.map +1 -1
  27. package/dist/{errors-5lj1EWgs.d.ts → errors-C4vZPqXf.d.ts} +2 -2
  28. package/dist/{errors-CE-lMBi2.d.cts → errors-DrcpYVfZ.d.cts} +2 -2
  29. package/dist/errors.d.cts +3 -2
  30. package/dist/eval.cjs +660 -370
  31. package/dist/eval.cjs.map +1 -1
  32. package/dist/eval.js +660 -370
  33. package/dist/eval.js.map +1 -1
  34. package/dist/generate-object.d.ts +19 -4
  35. package/dist/index.cjs +867 -371
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.d.cts +274 -16
  38. package/dist/index.d.ts +274 -16
  39. package/dist/index.js +863 -373
  40. package/dist/index.js.map +1 -1
  41. package/dist/internal/agent-loop/loop-types.d.ts +2 -0
  42. package/dist/internal/agent-loop/tool-result-guard.d.ts +1 -0
  43. package/dist/internal/llm/tool-result-content.d.ts +40 -0
  44. package/dist/internal/llm/types.d.ts +6 -1
  45. package/dist/internal/persistence/conversation-storage-fs.d.cts +3 -1
  46. package/dist/internal/persistence/conversation-storage-fs.d.ts +3 -1
  47. package/dist/internal/persistence/conversation-storage-memory.d.cts +3 -1
  48. package/dist/internal/persistence/conversation-storage-memory.d.ts +3 -1
  49. package/dist/internal/persistence/session-meta.d.cts +13 -0
  50. package/dist/internal/persistence/session-meta.d.ts +13 -0
  51. package/dist/internal/runtime/model-selection.d.ts +14 -0
  52. package/dist/internal/structured-output-helpers.d.ts +1 -1
  53. package/dist/permission-engine.d.ts +32 -1
  54. package/dist/{run-BgfBWX-z.d.cts → run-BMo8yRwK.d.cts} +262 -19
  55. package/dist/{run-BgfBWX-z.d.ts → run-BMo8yRwK.d.ts} +262 -19
  56. package/dist/stream-object.d.ts +2 -1
  57. package/dist/tool-error.d.ts +30 -0
  58. package/dist/types/agent-prims.d.ts +10 -8
  59. package/dist/types/agent.d.ts +22 -1
  60. package/dist/types/content-blocks.d.ts +47 -0
  61. package/dist/types/conversation-storage.d.ts +38 -0
  62. package/dist/types/index.d.ts +1 -0
  63. package/dist/types/messages.d.ts +2 -9
  64. package/dist/types/run-events.d.ts +84 -0
  65. package/dist/types/run.d.ts +115 -1
  66. package/dist/types/session.d.ts +99 -0
  67. package/dist/types/workflow.d.ts +7 -0
  68. package/dist/workflow.cjs +7 -2
  69. package/dist/workflow.cjs.map +1 -1
  70. package/dist/workflow.d.cts +2 -0
  71. package/dist/workflow.d.ts +2 -0
  72. package/dist/workflow.js +7 -2
  73. package/dist/workflow.js.map +1 -1
  74. package/package.json +3 -23
  75. package/dist/internal/observability/context.d.cts +0 -23
  76. package/dist/internal/observability/context.d.ts +0 -23
  77. package/dist/internal/observability/index.cjs +0 -38
  78. package/dist/internal/observability/index.cjs.map +0 -1
  79. package/dist/internal/observability/index.d.cts +0 -8
  80. package/dist/internal/observability/index.d.ts +0 -8
  81. package/dist/internal/observability/index.js +0 -33
  82. package/dist/internal/observability/index.js.map +0 -1
  83. package/dist/internal/plugins/index.cjs +0 -363
  84. package/dist/internal/plugins/index.cjs.map +0 -1
  85. package/dist/internal/plugins/index.js +0 -357
  86. package/dist/internal/plugins/index.js.map +0 -1
  87. package/dist/internal/workflow/index.d.ts +0 -12
  88. package/dist/server/adapter/index.d.cts +0 -8
  89. 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
  };
@@ -6804,23 +7215,27 @@ var init_skills_manager = __esm({
6804
7215
  "src/internal/runtime/skills/skills-manager.ts"() {
6805
7216
  init_discover_skills();
6806
7217
  SkillsManager = class {
6807
- constructor(cwd, _enabled, settingSourcesIncludeProject) {
7218
+ constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
6808
7219
  this.cwd = cwd;
6809
7220
  this.settingSourcesIncludeProject = settingSourcesIncludeProject;
7221
+ this.skillsDir = skillsDir;
7222
+ this.inline = inline;
6810
7223
  }
6811
7224
  cwd;
6812
7225
  settingSourcesIncludeProject;
7226
+ skillsDir;
7227
+ inline;
6813
7228
  skills = [];
6814
7229
  async initialize() {
6815
7230
  if (!this.settingSourcesIncludeProject) {
6816
- this.skills = [];
7231
+ this.skills = this.mergeInline([]);
6817
7232
  return;
6818
7233
  }
6819
7234
  await this.refresh();
6820
7235
  }
6821
7236
  async refresh() {
6822
- const skillsRoot = join(this.cwd, ".theokit", "skills");
6823
- this.skills = await discoverSkills(skillsRoot, {
7237
+ const skillsRoot = this.skillsDir ?? join(this.cwd, ".theokit", "skills");
7238
+ const discovered = await discoverSkills(skillsRoot, {
6824
7239
  onInvalidSkill: (info) => {
6825
7240
  process.stderr.write(
6826
7241
  `[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
@@ -6828,6 +7243,13 @@ var init_skills_manager = __esm({
6828
7243
  );
6829
7244
  }
6830
7245
  });
7246
+ this.skills = this.mergeInline(discovered);
7247
+ }
7248
+ /** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
7249
+ mergeInline(discovered) {
7250
+ if (this.inline === void 0 || this.inline.length === 0) return discovered;
7251
+ const inlineNames = new Set(this.inline.map((s) => s.name));
7252
+ return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
6831
7253
  }
6832
7254
  list() {
6833
7255
  return Promise.resolve(this.skills);
@@ -6865,7 +7287,7 @@ function bootstrapSubmanagers(args) {
6865
7287
  const providerCount = (args.options.providers?.routes?.length ?? 0) + enabledPluginNames(args.options.plugins).length;
6866
7288
  if (providerCount > 0 || args.options.providers !== void 0) {
6867
7289
  out.providers = new ProvidersManagerImpl(
6868
- args.options.model,
7290
+ normalizeModel(args.options.model),
6869
7291
  args.options.providers,
6870
7292
  args.options.plugins
6871
7293
  );
@@ -6874,7 +7296,10 @@ function bootstrapSubmanagers(args) {
6874
7296
  out.skillsManager = new SkillsManager(
6875
7297
  args.workspaceCwd,
6876
7298
  args.options.skills?.enabled,
6877
- args.settingSourcesIncludeProject
7299
+ args.settingSourcesIncludeProject,
7300
+ // M22 — custom skills directory + inline (code-defined) skills.
7301
+ args.options.skills?.skillsDir,
7302
+ args.options.skills?.inline
6878
7303
  );
6879
7304
  const localSkills = out.skillsManager;
6880
7305
  out.skills = { list: () => localSkills.list() };
@@ -6899,6 +7324,7 @@ var init_local_agent_bootstrap = __esm({
6899
7324
  init_enabled_names();
6900
7325
  init_providers_manager();
6901
7326
  init_context_manager();
7327
+ init_model_selection();
6902
7328
  init_plugins_manager();
6903
7329
  init_agent_registry();
6904
7330
  init_skills_manager();
@@ -6947,6 +7373,7 @@ function createLocalRun(options) {
6947
7373
  projectMcpServers: options.projectMcpServers,
6948
7374
  ...options.persistMemoryFact !== void 0 ? { persistMemoryFact: options.persistMemoryFact } : {}
6949
7375
  });
7376
+ if (options.sendOptions.origin !== void 0) script.origin = options.sendOptions.origin;
6950
7377
  const handle = new LocalRun({
6951
7378
  id,
6952
7379
  agentId: options.agentId,
@@ -7647,6 +8074,19 @@ var init_loop_llm_stream = __esm({
7647
8074
  init_message_builders();
7648
8075
  }
7649
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
+ });
7650
8090
  async function withToolWhitelist(whitelist, fn) {
7651
8091
  return toolWhitelistStore.run(whitelist, fn);
7652
8092
  }
@@ -7818,6 +8258,27 @@ var init_repair_middleware = __esm({
7818
8258
  }
7819
8259
  });
7820
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
+
7821
8282
  // src/internal/runtime/tools/shell-tool.ts
7822
8283
  async function runShell(options) {
7823
8284
  if (options.sandbox === true && isObviouslyUnsafe(options.command)) {
@@ -7876,9 +8337,13 @@ async function runHandlerTool(kind, handler, call, signal, context) {
7876
8337
  return { stdout: "", stderr: `${kind} tool ${call.name} has no handler`, exitCode: 127 };
7877
8338
  }
7878
8339
  try {
7879
- const stdout = await handler(call.input, { signal, context });
7880
- return { stdout, stderr: "", exitCode: 0 };
8340
+ const out = await handler(call.input, { signal, context });
8341
+ if (typeof out !== "string") return { stdout: "", stderr: "", exitCode: 0, content: out };
8342
+ return { stdout: out, stderr: "", exitCode: 0 };
7881
8343
  } catch (cause) {
8344
+ if (cause instanceof ToolError) {
8345
+ return { stdout: "", stderr: cause.message, exitCode: 1, content: cause.content };
8346
+ }
7882
8347
  const message = cause instanceof Error ? cause.message : String(cause);
7883
8348
  return { stdout: "", stderr: message, exitCode: 1 };
7884
8349
  }
@@ -7923,6 +8388,7 @@ ${result.stderr}`.trim();
7923
8388
  }
7924
8389
  var init_tool_executors = __esm({
7925
8390
  "src/internal/agent-loop/tool-executors.ts"() {
8391
+ init_tool_error();
7926
8392
  init_shell_tool();
7927
8393
  }
7928
8394
  });
@@ -8007,6 +8473,11 @@ async function dispatchSingleCall(inputs, tools, call, events, parentSpan) {
8007
8473
  toolSpan?.end();
8008
8474
  return fileVeto;
8009
8475
  }
8476
+ emitRunEvent(inputs.runEventSink, {
8477
+ type: "tool_progress",
8478
+ toolName: workingCall.name,
8479
+ toolCallId: callId
8480
+ });
8010
8481
  const result = await runToolWithLifecycle(inputs, resolved, workingCall, callId);
8011
8482
  await inputs.pluginManager?.runPostToolCallHooks({
8012
8483
  name: workingCall.name,
@@ -8033,6 +8504,13 @@ function applyRepairAndExtractCall(tools, call) {
8033
8504
  function vetoFromForkWhitelist(inputs, call, callId, events) {
8034
8505
  const whitelistDecision = checkToolWhitelist(call.name);
8035
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
+ });
8036
8514
  events.push(buildToolUseRunning(inputs, callId, call));
8037
8515
  events.push(
8038
8516
  buildToolUseCompleted(inputs, callId, call, {
@@ -8069,6 +8547,13 @@ async function vetoFromPluginPreHook(inputs, call, callId, events) {
8069
8547
  runId: inputs.runId
8070
8548
  });
8071
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
+ });
8072
8557
  events.push(
8073
8558
  buildToolUseCompleted(inputs, callId, call, {
8074
8559
  stdout: "",
@@ -8091,6 +8576,13 @@ async function vetoFromFileHookPreDecision(inputs, call, callId, events) {
8091
8576
  runId: inputs.runId
8092
8577
  });
8093
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
+ });
8094
8586
  events.push(
8095
8587
  buildToolUseCompleted(inputs, callId, call, {
8096
8588
  stdout: "",
@@ -8134,7 +8626,9 @@ async function runToolWithLifecycle(inputs, resolved, call, callId) {
8134
8626
  await safeEmitToolHook(inputs.onToolEnd, {
8135
8627
  toolName: call.name,
8136
8628
  args: call.input,
8137
- 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,
8138
8632
  conversationId: inputs.agentId,
8139
8633
  callId,
8140
8634
  durationMs
@@ -8156,7 +8650,10 @@ function finalizeSpanAndPostHook(inputs, call, callId, result, events, toolSpan)
8156
8650
  output: {
8157
8651
  stdout: result.stdout,
8158
8652
  stderr: result.stderr,
8159
- 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 } : {}
8160
8657
  },
8161
8658
  agentId: inputs.agentId,
8162
8659
  runId: inputs.runId
@@ -8169,7 +8666,9 @@ function finalizeSpanAndPostHook(inputs, call, callId, result, events, toolSpan)
8169
8666
  return {
8170
8667
  type: "tool_result",
8171
8668
  toolUseId: call.id,
8172
- 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),
8173
8672
  ...result.exitCode !== 0 && result.exitCode !== void 0 ? { isError: true } : {}
8174
8673
  };
8175
8674
  }
@@ -8219,6 +8718,7 @@ function buildToolUseCompleted(inputs, callId, call, result) {
8219
8718
  }
8220
8719
  var init_tool_dispatch = __esm({
8221
8720
  "src/internal/agent-loop/tool-dispatch.ts"() {
8721
+ init_run_events();
8222
8722
  init_ids();
8223
8723
  init_async_local_storage();
8224
8724
  init_map_with_concurrency();
@@ -8229,6 +8729,33 @@ var init_tool_dispatch = __esm({
8229
8729
  }
8230
8730
  });
8231
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
+
8232
8759
  // src/internal/agent-loop/tool-result-guard.ts
8233
8760
  function guardText(content, opts) {
8234
8761
  let out = content;
@@ -8246,12 +8773,17 @@ ${CLOSE}`;
8246
8773
  function applyToolResultGuard(parts, opts) {
8247
8774
  if (opts.delimit !== true && opts.redactPii !== true) return parts;
8248
8775
  return parts.map(
8249
- (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
+ )
8250
8781
  );
8251
8782
  }
8252
8783
  var OPEN, CLOSE, PII_PATTERNS;
8253
8784
  var init_tool_result_guard = __esm({
8254
8785
  "src/internal/agent-loop/tool-result-guard.ts"() {
8786
+ init_tool_result_content();
8255
8787
  OPEN = "<untrusted-tool-output>";
8256
8788
  CLOSE = "</untrusted-tool-output>";
8257
8789
  PII_PATTERNS = [
@@ -9284,8 +9816,8 @@ var init_vertex = __esm({
9284
9816
 
9285
9817
  // src/internal/providers/builtin/index.ts
9286
9818
  function registerBuiltins() {
9287
- if (registered2) return;
9288
- registered2 = true;
9819
+ if (registered3) return;
9820
+ registered3 = true;
9289
9821
  registerProvider(ANTHROPIC);
9290
9822
  registerProvider(OPENAI);
9291
9823
  registerProvider(OPENROUTER);
@@ -9297,7 +9829,7 @@ function registerBuiltins() {
9297
9829
  registerProvider(VERTEX);
9298
9830
  registerCatalogProviders();
9299
9831
  }
9300
- var registered2;
9832
+ var registered3;
9301
9833
  var init_builtin = __esm({
9302
9834
  "src/internal/providers/builtin/index.ts"() {
9303
9835
  init_catalog_loader();
@@ -9311,7 +9843,7 @@ var init_builtin = __esm({
9311
9843
  init_openai();
9312
9844
  init_openrouter();
9313
9845
  init_vertex();
9314
- registered2 = false;
9846
+ registered3 = false;
9315
9847
  }
9316
9848
  });
9317
9849
 
@@ -9556,7 +10088,9 @@ function toAnthropicWireMessage(message) {
9556
10088
  return {
9557
10089
  type: "tool_result",
9558
10090
  tool_use_id: part.toolUseId,
9559
- content: part.content,
10091
+ // SE7 — this wire is block-capable: strings pass through, structured
10092
+ // text/image blocks are forwarded natively.
10093
+ content: toBlockToolResultContent(part.content),
9560
10094
  ...part.isError === true ? { is_error: true } : {}
9561
10095
  };
9562
10096
  });
@@ -9633,6 +10167,7 @@ function encodeAnthropicSystem(system) {
9633
10167
  var init_anthropic_shared = __esm({
9634
10168
  "src/internal/llm/anthropic-shared.ts"() {
9635
10169
  init_finish();
10170
+ init_tool_result_content();
9636
10171
  }
9637
10172
  });
9638
10173
 
@@ -10587,7 +11122,8 @@ function toOllamaMessages(message) {
10587
11122
  if (part.type === "tool_result") {
10588
11123
  out.push({
10589
11124
  role: "tool",
10590
- content: part.content,
11125
+ // SE7 — string-only tool role: text blocks flatten; image fails fast.
11126
+ content: toStringToolResultContent(part.content, "ollama"),
10591
11127
  tool_name: part.toolUseId
10592
11128
  });
10593
11129
  }
@@ -10628,6 +11164,7 @@ var init_ollama_native = __esm({
10628
11164
  "src/internal/llm/ollama-native.ts"() {
10629
11165
  init_ollama2();
10630
11166
  init_finish();
11167
+ init_tool_result_content();
10631
11168
  OllamaNativeClient = class {
10632
11169
  constructor(options) {
10633
11170
  this.options = options;
@@ -10992,7 +11529,9 @@ function userOrToolMessages(message) {
10992
11529
  out.push({
10993
11530
  role: "tool",
10994
11531
  tool_call_id: part.toolUseId,
10995
- content: part.content
11532
+ // SE7 — this wire's tool role is string-only: text blocks flatten; an
11533
+ // image block fails fast (ConfigurationError).
11534
+ content: toStringToolResultContent(part.content, "openai")
10996
11535
  });
10997
11536
  }
10998
11537
  }
@@ -11023,6 +11562,7 @@ var init_openai2 = __esm({
11023
11562
  init_finish();
11024
11563
  init_hermes_tool_extract();
11025
11564
  init_sse();
11565
+ init_tool_result_content();
11026
11566
  OpenAIClient = class {
11027
11567
  constructor(options) {
11028
11568
  this.options = options;
@@ -12262,18 +12802,20 @@ var init_personality_filter = __esm({
12262
12802
  function createRealLocalRun(options) {
12263
12803
  const { userText, id, startTime } = prepareRunContext(options.message);
12264
12804
  const supported = /* @__PURE__ */ new Set(["stream", "wait", "cancel", "conversation"]);
12265
- const unusedFixtureScript = {
12805
+ const runScript = {
12266
12806
  events: [],
12267
12807
  finalStatus: "running",
12268
12808
  cancellable: false,
12269
- conversation: []
12809
+ conversation: [],
12810
+ // SE3 — carry the turn's provenance so buildResult forwards it onto RunResult.origin.
12811
+ ...options.sendOptions.origin !== void 0 ? { origin: options.sendOptions.origin } : {}
12270
12812
  };
12271
12813
  const handle = new RealLocalRun(
12272
12814
  {
12273
12815
  id,
12274
12816
  agentId: options.agentId,
12275
12817
  model: options.model,
12276
- script: unusedFixtureScript,
12818
+ script: runScript,
12277
12819
  supportedOps: supported,
12278
12820
  startTime
12279
12821
  },
@@ -12384,6 +12926,8 @@ function buildLoopInputs(options, runId, userText) {
12384
12926
  // M7 — forward SendOptions.context to the loop so every tool handler receives
12385
12927
  // it on `ctx.context` (shared run config set once, e.g. projectRoot).
12386
12928
  ...options.sendOptions.context !== void 0 ? { context: options.sendOptions.context } : {},
12929
+ // SE2 — forward the opt-in typed runtime-event sink to the loop.
12930
+ ...options.sendOptions.onRunEvent !== void 0 ? { runEventSink: options.sendOptions.onRunEvent } : {},
12387
12931
  // #58 / #57 — forward the per-tool timeout + tool-result guard so a consumer
12388
12932
  // can enable them via SendOptions (not only internal AgentLoopInputs).
12389
12933
  ...options.sendOptions.perToolTimeoutMs !== void 0 ? { perToolTimeoutMs: options.sendOptions.perToolTimeoutMs } : {},
@@ -15457,29 +16001,6 @@ var init_judge_call = __esm({
15457
16001
  }
15458
16002
  });
15459
16003
 
15460
- // src/internal/runtime/registry/agent-factory-registry.ts
15461
- var agent_factory_registry_exports = {};
15462
- __export(agent_factory_registry_exports, {
15463
- getAgentFacade: () => getAgentFacade,
15464
- setAgentFacade: () => setAgentFacade
15465
- });
15466
- function setAgentFacade(facade) {
15467
- registered3 = facade;
15468
- }
15469
- function getAgentFacade() {
15470
- if (registered3 === void 0) {
15471
- throw new Error(
15472
- "internal: Agent facade not registered. The `agent.ts` module must be loaded before internal subsystems (LocalAgent.runUntil/fork, eval, scorers, cron) invoke it."
15473
- );
15474
- }
15475
- return registered3;
15476
- }
15477
- var registered3;
15478
- var init_agent_factory_registry = __esm({
15479
- "src/internal/runtime/registry/agent-factory-registry.ts"() {
15480
- }
15481
- });
15482
-
15483
16004
  // src/internal/runtime/lifecycle/run-to-completion.ts
15484
16005
  var run_to_completion_exports = {};
15485
16006
  __export(run_to_completion_exports, {
@@ -15644,14 +16165,14 @@ async function forkAgentImpl(parent, options, deps) {
15644
16165
  return {
15645
16166
  result: result.result,
15646
16167
  toolCalls: [],
15647
- usage: extractUsage(result)
16168
+ usage: extractUsage2(result)
15648
16169
  };
15649
16170
  });
15650
16171
  } finally {
15651
16172
  await fork.dispose();
15652
16173
  }
15653
16174
  }
15654
- function extractUsage(result) {
16175
+ function extractUsage2(result) {
15655
16176
  if (typeof result !== "object" || result === null) {
15656
16177
  return { inputTokens: 0, outputTokens: 0 };
15657
16178
  }
@@ -15810,7 +16331,7 @@ var init_local_agent_memory_hooks = __esm({
15810
16331
  async function executeSendLocked(inputs, message, options) {
15811
16332
  if (inputs.disposed) throw new AgentDisposedError(inputs.agentId);
15812
16333
  await consumePending(inputs.agentId, inputs.invalidationPending, inputs.clearInvalidation, inputs.reload);
15813
- inputs.applyModelOverride(options.model);
16334
+ inputs.applyModelOverride(normalizeModel(options.model));
15814
16335
  const userText = typeof message === "string" ? message : message.text;
15815
16336
  if (inputs.options.onBeforeSend !== void 0) {
15816
16337
  await inputs.options.onBeforeSend({
@@ -15879,6 +16400,7 @@ var init_local_agent_send = __esm({
15879
16400
  init_abort_utils();
15880
16401
  init_memory_path_selector();
15881
16402
  init_memory_store();
16403
+ init_model_selection();
15882
16404
  init_agent_session();
15883
16405
  init_safe_call();
15884
16406
  init_local_agent_invalidate();
@@ -16458,6 +16980,7 @@ function includesSetting(options, source) {
16458
16980
  var LocalAgent;
16459
16981
  var init_local_agent = __esm({
16460
16982
  "src/internal/runtime/local-agent/local-agent.ts"() {
16983
+ init_agent_generate();
16461
16984
  init_errors();
16462
16985
  init_ids();
16463
16986
  init_cwd_mutex();
@@ -16468,6 +16991,7 @@ var init_local_agent = __esm({
16468
16991
  init_hooks_executor();
16469
16992
  init_post_run_lifecycle();
16470
16993
  init_memory_path_selector();
16994
+ init_model_selection();
16471
16995
  init_agent_registry();
16472
16996
  init_live_agent_registry();
16473
16997
  init_agent_session();
@@ -16544,7 +17068,7 @@ var init_local_agent = __esm({
16544
17068
  constructor(options) {
16545
17069
  this.agentId = options.agentId ?? generateLocalAgentId();
16546
17070
  this._telemetry = createTelemetry(options.telemetry);
16547
- this.model = options.model;
17071
+ this.model = normalizeModel(options.model);
16548
17072
  this.options = options;
16549
17073
  this.workspaceCwd = resolveCwd(options.local?.cwd);
16550
17074
  this.conversationStorage = options.conversationStorage;
@@ -16611,6 +17135,11 @@ var init_local_agent = __esm({
16611
17135
  hooks() {
16612
17136
  return this.hooksExecutor;
16613
17137
  }
17138
+ // SE9 — integrated structured output; delegates to the shared helper.
17139
+ generate(message, options) {
17140
+ const { apiKey, local } = this.options;
17141
+ return agentGenerate(this, this.model, apiKey, local, message, options);
17142
+ }
16614
17143
  async send(message, options = {}) {
16615
17144
  if (options.tools !== void 0 && options.tools.length > 0) {
16616
17145
  validateToolCatalog(options.tools);
@@ -16843,6 +17372,7 @@ var init_local_agent = __esm({
16843
17372
  }
16844
17373
  });
16845
17374
  async function runCreateUnderSpan(options, span) {
17375
+ options = { ...options, model: normalizeModel(options.model) };
16846
17376
  validateAgentOptions(options);
16847
17377
  validateCloudToolParity(options);
16848
17378
  await guardAgainstIdCollision(options);
@@ -16916,7 +17446,10 @@ async function createLocalAgent(options) {
16916
17446
  const willFlowToProvider = !isFixtureApiKey(apiKey) && !shouldUseRealLocalRuntime(apiKey);
16917
17447
  const shape = validateApiKeyShape(apiKey, {
16918
17448
  strict: willFlowToProvider,
16919
- ...willFlowToProvider ? { provider: providerFromModelId(options.model?.id) } : {}
17449
+ // `options.model` is already normalized by `runCreateUnderSpan`; `normalizeModel`
17450
+ // here is the idempotent narrowing of the widened public type (`{id}` passes
17451
+ // through by reference) — cleaner than an `as` cast.
17452
+ ...willFlowToProvider ? { provider: providerFromModelId(normalizeModel(options.model)?.id) } : {}
16920
17453
  });
16921
17454
  if (shape.malformed) {
16922
17455
  throw new AuthenticationError(shape.message, { code: "malformed_api_key" });
@@ -16982,6 +17515,10 @@ async function rehydrateExistingAgent(agentId, existing, options) {
16982
17515
  ...existing.options,
16983
17516
  ...options,
16984
17517
  ...mergedLocal !== void 0 ? { local: mergedLocal } : {},
17518
+ // SE8 — normalize a caller-supplied bare-string model override at this resume
17519
+ // boundary (Agent.resume never flows through runCreateUnderSpan). Cloud resume
17520
+ // honors it; local resume forces the persisted model below.
17521
+ model: normalizeModel(options.model ?? existing.options.model),
16985
17522
  mcpServers: void 0,
16986
17523
  agentId
16987
17524
  };
@@ -17064,216 +17601,11 @@ var init_agent_helpers = __esm({
17064
17601
  init_cloud_agent();
17065
17602
  init_cloud_tool_parity();
17066
17603
  init_local_agent();
17604
+ init_model_selection();
17067
17605
  init_agent_registry();
17068
17606
  init_validate_agent_options();
17069
17607
  }
17070
17608
  });
17071
- function toJsonSchema(schema, options = { unrepresentable: "any" }) {
17072
- return toJSONSchema(schema, options);
17073
- }
17074
- var init_to_json_schema = __esm({
17075
- "src/internal/zod/to-json-schema.ts"() {
17076
- }
17077
- });
17078
- function requireZod() {
17079
- if (cachedZ !== void 0) return cachedZ;
17080
- const r = createRequire(import.meta.url);
17081
- let mod;
17082
- try {
17083
- mod = r("zod");
17084
- } catch (cause) {
17085
- throw new ConfigurationError(
17086
- 'Structured output requires the optional peer dependency `zod`. Add `"zod": "^3.25.0 || ^4.0.0"` to your package.json and reinstall.',
17087
- { code: "zod_not_installed", cause }
17088
- );
17089
- }
17090
- cachedZ = mod.z ?? mod;
17091
- return cachedZ;
17092
- }
17093
- function makeOutputTool(jsonSchema, onCapture) {
17094
- return {
17095
- name: "output",
17096
- description: "Call this tool with your final structured answer. Match the JSON schema exactly.",
17097
- inputSchema: jsonSchema,
17098
- handler: (input) => {
17099
- const out = onCapture(input);
17100
- if (typeof out === "string") return out;
17101
- if (out instanceof Promise) return out;
17102
- return "";
17103
- }
17104
- };
17105
- }
17106
- function buildTransientAgentOptions(params) {
17107
- return {
17108
- model: params.model,
17109
- local: params.local,
17110
- tools: [params.outputTool],
17111
- systemPrompt: params.systemPrompt ?? "You produce structured output by calling the `output` tool exactly once. Match the JSON schema.",
17112
- ...params.apiKey !== void 0 ? { apiKey: params.apiKey } : {},
17113
- ...params.providers !== void 0 ? { providers: params.providers } : {}
17114
- };
17115
- }
17116
- function extractUsage2(result) {
17117
- const u = result.usage;
17118
- if (u === void 0) return { inputTokens: 0, outputTokens: 0 };
17119
- return { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 };
17120
- }
17121
- function buildToolPrompt(prompt) {
17122
- return `${prompt}
17123
-
17124
- Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
17125
- }
17126
- function setupStructuredOutput(schema, maxRetries) {
17127
- const z7 = requireZod();
17128
- const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
17129
- return {
17130
- z: z7,
17131
- jsonSchema,
17132
- maxRetries: maxRetries ?? 1,
17133
- initialUsage: { inputTokens: 0, outputTokens: 0 }
17134
- };
17135
- }
17136
- async function disposeAndDeleteTransient(agent, deletor) {
17137
- await agent.dispose();
17138
- try {
17139
- await deletor(agent.agentId);
17140
- } catch {
17141
- }
17142
- }
17143
- var cachedZ;
17144
- var init_structured_output_helpers = __esm({
17145
- "src/internal/structured-output-helpers.ts"() {
17146
- init_errors();
17147
- init_to_json_schema();
17148
- }
17149
- });
17150
-
17151
- // src/generate-object.ts
17152
- var generate_object_exports = {};
17153
- __export(generate_object_exports, {
17154
- GenerateObjectError: () => GenerateObjectError,
17155
- generateObjectImpl: () => generateObjectImpl
17156
- });
17157
- function salvagePartial(schema, raw) {
17158
- if (typeof raw !== "object" || raw === null) return raw;
17159
- const shape = schema.shape;
17160
- if (shape === void 0 || typeof shape !== "object") return raw;
17161
- const rawObj = raw;
17162
- const out = {};
17163
- for (const [key, fieldSchema] of Object.entries(shape)) {
17164
- if (typeof fieldSchema?.safeParse !== "function") continue;
17165
- const parsed = fieldSchema.safeParse(rawObj[key]);
17166
- if (parsed.success) out[key] = parsed.data;
17167
- }
17168
- return out;
17169
- }
17170
- async function generateObjectImpl(options, deps) {
17171
- const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(
17172
- options.schema,
17173
- options.maxRetries
17174
- );
17175
- let capturedRaw;
17176
- let lastUsage = initialUsage;
17177
- const sentinel = /* @__PURE__ */ Symbol("generate-object-sentinel");
17178
- class CaptureSentinel extends Error {
17179
- constructor(captured) {
17180
- super("generate-object-capture");
17181
- this.captured = captured;
17182
- }
17183
- captured;
17184
- [sentinel] = true;
17185
- }
17186
- const outputTool = makeOutputTool(jsonSchema, (input) => {
17187
- if (capturedRaw === void 0) {
17188
- capturedRaw = input;
17189
- }
17190
- throw new CaptureSentinel(input);
17191
- });
17192
- const agentOptions = buildTransientAgentOptions({
17193
- model: options.model,
17194
- local: options.local,
17195
- outputTool,
17196
- ...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
17197
- ...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
17198
- ...options.providers !== void 0 ? { providers: options.providers } : {}
17199
- });
17200
- const agent = await deps.create(agentOptions);
17201
- try {
17202
- const userMessage = buildToolPrompt(options.prompt);
17203
- let lastParseError;
17204
- for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
17205
- capturedRaw = void 0;
17206
- const run = await agent.send(userMessage);
17207
- const result = await run.wait();
17208
- lastUsage = extractUsage2(result);
17209
- if (capturedRaw === void 0) {
17210
- if (result.status === "error" && result.error !== void 0) {
17211
- throw new GenerateObjectError(
17212
- "no_tool_call",
17213
- `Agent run failed before the model could reply: ${result.error.message ?? "unknown error"} [${result.error.code ?? "?"}]`,
17214
- result.error
17215
- );
17216
- }
17217
- if (attempt === maxRetries) {
17218
- throw new GenerateObjectError(
17219
- "no_tool_call",
17220
- "The model returned text instead of calling the `output` tool."
17221
- );
17222
- }
17223
- continue;
17224
- }
17225
- const parsed = options.schema.safeParse(capturedRaw);
17226
- if (parsed.success) {
17227
- return {
17228
- object: parsed.data,
17229
- raw: capturedRaw,
17230
- usage: lastUsage,
17231
- finishReason: "tool_use"
17232
- };
17233
- }
17234
- lastParseError = parsed.error;
17235
- }
17236
- if (options.errorStrategy === "return-raw") {
17237
- return {
17238
- object: capturedRaw,
17239
- raw: capturedRaw,
17240
- usage: lastUsage,
17241
- finishReason: "tool_use"
17242
- };
17243
- }
17244
- if (options.errorStrategy === "return-partial") {
17245
- return {
17246
- object: salvagePartial(options.schema, capturedRaw),
17247
- raw: capturedRaw,
17248
- usage: lastUsage,
17249
- finishReason: "tool_use"
17250
- };
17251
- }
17252
- throw new GenerateObjectError(
17253
- "parse_failed",
17254
- "Schema parse failed after all retries.",
17255
- lastParseError
17256
- );
17257
- } finally {
17258
- await disposeAndDeleteTransient(agent, deps.delete);
17259
- }
17260
- }
17261
- var GenerateObjectError;
17262
- var init_generate_object = __esm({
17263
- "src/generate-object.ts"() {
17264
- init_structured_output_helpers();
17265
- GenerateObjectError = class extends Error {
17266
- name = "GenerateObjectError";
17267
- code;
17268
- cause;
17269
- constructor(code, message, cause) {
17270
- super(message);
17271
- this.code = code;
17272
- if (cause !== void 0) this.cause = cause;
17273
- }
17274
- };
17275
- }
17276
- });
17277
17609
 
17278
17610
  // src/stream-object.ts
17279
17611
  var stream_object_exports = {};
@@ -17329,7 +17661,7 @@ async function* streamObjectImpl(options, deps) {
17329
17661
  }
17330
17662
  }
17331
17663
  const result = await run.wait();
17332
- lastUsage = extractUsage2(result);
17664
+ lastUsage = extractUsage(result);
17333
17665
  if (capturedRaw === void 0) {
17334
17666
  if (result.status === "error" && result.error !== void 0) {
17335
17667
  throw new StreamObjectError(
@@ -17976,6 +18308,7 @@ var init_agent = __esm({
17976
18308
  };
17977
18309
  setAgentFacade({
17978
18310
  create: (options) => Agent.create(options),
18311
+ delete: (agentId) => Agent.delete(agentId),
17979
18312
  prompt: (message, options) => Agent.prompt(message, options),
17980
18313
  get: (agentId) => Agent.get(agentId),
17981
18314
  resume: (agentId, options) => Agent.resume(agentId, options),
@@ -18032,7 +18365,9 @@ var MessageBus = class {
18032
18365
  ...partial,
18033
18366
  from,
18034
18367
  to,
18035
- timestamp: Date.now()
18368
+ timestamp: Date.now(),
18369
+ // SE3 — provenance projection of the sender address (thin view over `from`).
18370
+ origin: { kind: "peer", from }
18036
18371
  };
18037
18372
  handler(message);
18038
18373
  }
@@ -18046,7 +18381,9 @@ var MessageBus = class {
18046
18381
  ...partial,
18047
18382
  from,
18048
18383
  to,
18049
- timestamp: Date.now()
18384
+ timestamp: Date.now(),
18385
+ // SE3 — provenance projection of the sender address (thin view over `from`).
18386
+ origin: { kind: "peer", from }
18050
18387
  };
18051
18388
  return Promise.race([
18052
18389
  Promise.resolve(handler(message)),