@theokit/agents 0.30.1 → 0.31.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.
@@ -27,13 +27,13 @@ import {
27
27
  } from "./chunk-7QVYU63E.js";
28
28
 
29
29
  // src/bridge/agent-execution-context.ts
30
- function createAgentExecutionContext(base, agent, run, toolCall) {
30
+ function createAgentExecutionContext(base, agent2, run, toolCall) {
31
31
  return {
32
32
  getRequest: /* @__PURE__ */ __name(() => base.getRequest(), "getRequest"),
33
33
  getUrl: /* @__PURE__ */ __name(() => base.getUrl(), "getUrl"),
34
34
  getClass: /* @__PURE__ */ __name(() => base.getClass(), "getClass"),
35
35
  getMethodName: /* @__PURE__ */ __name(() => base.getMethodName(), "getMethodName"),
36
- getAgent: /* @__PURE__ */ __name(() => agent, "getAgent"),
36
+ getAgent: /* @__PURE__ */ __name(() => agent2, "getAgent"),
37
37
  getRun: /* @__PURE__ */ __name(() => run, "getRun"),
38
38
  getToolCall: /* @__PURE__ */ __name(() => toolCall ?? null, "getToolCall"),
39
39
  isAgentContext: /* @__PURE__ */ __name(() => true, "isAgentContext")
@@ -982,7 +982,8 @@ async function loadSdkRuntime() {
982
982
  InMemoryConversationStorage: InMemory,
983
983
  FileSystemConversationStorage: "FileSystemConversationStorage" in sdk ? sdk.FileSystemConversationStorage : InMemory
984
984
  };
985
- } catch {
985
+ } catch (err) {
986
+ console.warn("[theokit] @theokit/sdk import failed:", err);
986
987
  return null;
987
988
  }
988
989
  }
@@ -1124,15 +1125,34 @@ function hasZodInputSchema(schema) {
1124
1125
  return typeof schema?.parse === "function";
1125
1126
  }
1126
1127
  __name(hasZodInputSchema, "hasZodInputSchema");
1127
- function buildSdkTools(compiledTools, defineTool, extraSdkTools = []) {
1128
+ function withRunContext(handler, runContext) {
1129
+ return (input, ctx) => handler(input, {
1130
+ signal: ctx?.signal,
1131
+ context: runContext
1132
+ });
1133
+ }
1134
+ __name(withRunContext, "withRunContext");
1135
+ function buildSdkTools(compiledTools, defineTool, extraSdkTools = [], runContext) {
1136
+ const has = runContext !== void 0;
1128
1137
  return [
1129
- ...compiledTools.map((t) => hasZodInputSchema(t.inputSchema) ? defineTool({
1130
- name: t.name,
1131
- description: t.description,
1132
- inputSchema: t.inputSchema,
1133
- handler: t.handler
1134
- }) : t),
1135
- ...extraSdkTools
1138
+ ...compiledTools.map((t) => {
1139
+ if (hasZodInputSchema(t.inputSchema)) {
1140
+ return defineTool({
1141
+ name: t.name,
1142
+ description: t.description,
1143
+ inputSchema: t.inputSchema,
1144
+ handler: has ? withRunContext(t.handler, runContext) : t.handler
1145
+ });
1146
+ }
1147
+ return has ? {
1148
+ ...t,
1149
+ handler: withRunContext(t.handler, runContext)
1150
+ } : t;
1151
+ }),
1152
+ ...extraSdkTools.map((t) => has ? {
1153
+ ...t,
1154
+ handler: withRunContext(t.handler, runContext)
1155
+ } : t)
1136
1156
  ];
1137
1157
  }
1138
1158
  __name(buildSdkTools, "buildSdkTools");
@@ -1140,6 +1160,7 @@ function createSdkAgentStream(compiled, compiledTools, apiKey, overrides = {}) {
1140
1160
  const model = overrides.model ?? compiled.model ?? "openai/gpt-4o-mini";
1141
1161
  const reasoningEffort = overrides.reasoningEffort ?? compiled.reasoningEffort;
1142
1162
  const { parseThinkTags, stripToolDialect } = resolveTextTransformFlags(compiled, overrides);
1163
+ const runContext = overrides.runContext ?? compiled.runContext;
1143
1164
  let storage = overrides.conversationStorage;
1144
1165
  return (message, sessionId, factoryOpts) => ({
1145
1166
  async *[Symbol.asyncIterator]() {
@@ -1155,51 +1176,35 @@ function createSdkAgentStream(compiled, compiledTools, apiKey, overrides = {}) {
1155
1176
  };
1156
1177
  return;
1157
1178
  }
1158
- const { Agent, defineTool, InMemoryConversationStorage, FileSystemConversationStorage } = rt;
1159
- const sdkTools = buildSdkTools(compiledTools, defineTool, overrides.sdkTools);
1160
- let agent;
1179
+ const { InMemoryConversationStorage, FileSystemConversationStorage } = rt;
1180
+ const sdkTools = buildSdkTools(compiledTools, rt.defineTool, overrides.sdkTools, runContext);
1181
+ let runContextSource;
1182
+ if (overrides.runContext !== void 0) {
1183
+ runContextSource = "per-run";
1184
+ } else if (compiled.runContext !== void 0) {
1185
+ runContextSource = "agent-level";
1186
+ } else {
1187
+ runContextSource = "none";
1188
+ }
1189
+ console.debug("[THEO_AGENT_M7_RUN_CONTEXT]", {
1190
+ source: runContextSource,
1191
+ keys: runContext !== void 0 ? Object.keys(runContext) : []
1192
+ });
1193
+ storage ??= newConversationStorage(compiled, InMemoryConversationStorage, FileSystemConversationStorage);
1161
1194
  try {
1162
- const { options: m8, applied } = assembleM8CreateOptions(compiled);
1163
- if (overrides.cwd !== void 0) m8.local = {
1164
- ...m8.local,
1165
- cwd: overrides.cwd
1166
- };
1167
- const extra = buildExtraCreateOptions(overrides, compiled);
1168
- storage ??= newConversationStorage(compiled, InMemoryConversationStorage, FileSystemConversationStorage);
1169
- if (applied.length > 0) {
1170
- console.debug("[THEO_AGENT_M8_RUNTIME_APPLIED]", {
1171
- skills: applied.includes("skills"),
1172
- context: applied.includes("context"),
1173
- projectContext: applied.includes("projectContext")
1174
- });
1175
- }
1176
- agent = await Agent.getOrCreate(sessionId, {
1195
+ yield* streamSdkAgent(rt, compiled, sdkTools, storage, {
1177
1196
  apiKey,
1178
- model: buildModelSelection(model, reasoningEffort),
1179
- tools: sdkTools,
1180
- ...m8,
1181
- ...extra,
1182
- conversationStorage: storage
1183
- });
1184
- const queue = createAsyncQueue();
1185
- const { state, onDelta } = createDeltaSink(queue);
1186
- const sendPromise = agent.send(message, factoryOpts?.disableTools === true ? {
1187
- onDelta,
1188
- toolChoice: "none"
1189
- } : {
1190
- onDelta
1191
- });
1192
- const openStream = /* @__PURE__ */ __name(async () => (await sendPromise).stream(), "openStream");
1193
- const merged = mergeDeltaStream(queue, openStream, runId, state);
1194
- for await (const event of applyTextTransforms(merged, {
1197
+ model,
1198
+ reasoningEffort,
1199
+ overrides,
1195
1200
  parseThinkTags,
1196
- stripToolDialect
1197
- })) {
1198
- yield event;
1199
- }
1200
- if (!state.sawError) {
1201
- yield realUsageDone(await (await sendPromise).wait(), t0);
1202
- }
1201
+ stripToolDialect,
1202
+ sessionId,
1203
+ message,
1204
+ factoryOpts,
1205
+ runId,
1206
+ t0
1207
+ });
1203
1208
  } catch (err) {
1204
1209
  yield {
1205
1210
  type: "error",
@@ -1207,13 +1212,59 @@ function createSdkAgentStream(compiled, compiledTools, apiKey, overrides = {}) {
1207
1212
  message: err instanceof Error ? err.message : "SDK agent error",
1208
1213
  retryable: false
1209
1214
  };
1210
- } finally {
1211
- await agent?.dispose();
1212
1215
  }
1213
1216
  }
1214
1217
  });
1215
1218
  }
1216
1219
  __name(createSdkAgentStream, "createSdkAgentStream");
1220
+ async function* streamSdkAgent(rt, compiled, sdkTools, storage, opts) {
1221
+ const { Agent } = rt;
1222
+ const { apiKey, model, reasoningEffort, overrides, parseThinkTags, stripToolDialect, sessionId, message, factoryOpts, runId, t0 } = opts;
1223
+ const { options: m8, applied } = assembleM8CreateOptions(compiled);
1224
+ if (overrides.cwd !== void 0) m8.local = {
1225
+ ...m8.local,
1226
+ cwd: overrides.cwd
1227
+ };
1228
+ const extra = buildExtraCreateOptions(overrides, compiled);
1229
+ if (applied.length > 0) {
1230
+ console.debug("[THEO_AGENT_M8_RUNTIME_APPLIED]", {
1231
+ skills: applied.includes("skills"),
1232
+ contextWindow: applied.includes("context"),
1233
+ projectContext: applied.includes("projectContext")
1234
+ });
1235
+ }
1236
+ const agent2 = await Agent.getOrCreate(sessionId, {
1237
+ apiKey,
1238
+ model: buildModelSelection(model, reasoningEffort),
1239
+ tools: sdkTools,
1240
+ ...m8,
1241
+ ...extra,
1242
+ conversationStorage: storage
1243
+ });
1244
+ try {
1245
+ const queue = createAsyncQueue();
1246
+ const { state, onDelta } = createDeltaSink(queue);
1247
+ const sendOptions = {
1248
+ onDelta
1249
+ };
1250
+ if (factoryOpts?.disableTools === true) sendOptions.toolChoice = "none";
1251
+ const sendPromise = agent2.send(message, sendOptions);
1252
+ const openStream = /* @__PURE__ */ __name(async () => (await sendPromise).stream(), "openStream");
1253
+ const merged = mergeDeltaStream(queue, openStream, runId, state);
1254
+ for await (const event of applyTextTransforms(merged, {
1255
+ parseThinkTags,
1256
+ stripToolDialect
1257
+ })) {
1258
+ yield event;
1259
+ }
1260
+ if (!state.sawError) {
1261
+ yield realUsageDone(await (await sendPromise).wait(), t0);
1262
+ }
1263
+ } finally {
1264
+ await agent2.dispose();
1265
+ }
1266
+ }
1267
+ __name(streamSdkAgent, "streamSdkAgent");
1217
1268
 
1218
1269
  // src/bridge/ui-message-stream-translator.ts
1219
1270
  function* closeOpenBlock(state, textId) {
@@ -1389,17 +1440,116 @@ function isAgentDefinition(value) {
1389
1440
  return typeof value === "object" && value !== null && value[AGENT_BRAND] === true;
1390
1441
  }
1391
1442
  __name(isAgentDefinition, "isAgentDefinition");
1443
+ function toCompiledTool(tool) {
1444
+ const handler = tool.handler;
1445
+ return {
1446
+ name: tool.name,
1447
+ description: tool.description,
1448
+ inputSchema: tool.inputSchema,
1449
+ handler: /* @__PURE__ */ __name((input, ctx) => handler(input, ctx), "handler")
1450
+ };
1451
+ }
1452
+ __name(toCompiledTool, "toCompiledTool");
1392
1453
  function compileAgentDefinition(def) {
1393
1454
  return {
1394
1455
  model: def.model,
1395
1456
  reasoningEffort: def.reasoningEffort,
1396
1457
  systemPrompt: def.system,
1397
- tools: def.tools ?? [],
1458
+ tools: (def.tools ?? []).map(toCompiledTool),
1398
1459
  agents: {},
1399
- stream: true
1460
+ stream: true,
1461
+ // M7 — run-context flows to CompiledAgentOptions.runContext (distinct from the
1462
+ // context-window `context` field the decorator path uses); absent ⇒ no key.
1463
+ ...def.context !== void 0 ? {
1464
+ runContext: def.context
1465
+ } : {},
1466
+ // M9 — guardrails flow through unchanged; the runner applies them at the input boundary.
1467
+ ...def.guardrails !== void 0 ? {
1468
+ guardrails: def.guardrails
1469
+ } : {},
1470
+ // M14 — HITL approvals compile into the same `hitl` map the decorator path produces.
1471
+ ...def.approvals !== void 0 ? {
1472
+ hitl: compileApprovals(def)
1473
+ } : {},
1474
+ // M13 — skills: a static list → SDK skills.enabled; a resolver → carried for the request path.
1475
+ ...compileSkillsSelection(def.skills)
1400
1476
  };
1401
1477
  }
1402
1478
  __name(compileAgentDefinition, "compileAgentDefinition");
1479
+ function compileSkillsSelection(skills) {
1480
+ if (skills === void 0) return {};
1481
+ if (typeof skills === "function") return {
1482
+ skillsResolver: skills
1483
+ };
1484
+ return {
1485
+ skills: {
1486
+ enabled: [
1487
+ ...skills
1488
+ ],
1489
+ autoInject: true
1490
+ }
1491
+ };
1492
+ }
1493
+ __name(compileSkillsSelection, "compileSkillsSelection");
1494
+ function compileApprovals(def) {
1495
+ const toolNames = new Set((def.tools ?? []).map((t) => t.name));
1496
+ const gates = /* @__PURE__ */ new Map();
1497
+ for (const [toolName, options] of Object.entries(def.approvals ?? {})) {
1498
+ if (!toolNames.has(toolName)) {
1499
+ throw new Error(`[@theokit/agents] defineAgent approval references unknown tool "${toolName}". Declared tools: ${[
1500
+ ...toolNames
1501
+ ].join(", ") || "(none)"}.`);
1502
+ }
1503
+ gates.set(toolName, options);
1504
+ }
1505
+ return gates;
1506
+ }
1507
+ __name(compileApprovals, "compileApprovals");
1508
+
1509
+ // src/bridge/agent-builder.ts
1510
+ function contextualTool(tool, _requiredContext) {
1511
+ return tool;
1512
+ }
1513
+ __name(contextualTool, "contextualTool");
1514
+ function makeBuilder(config) {
1515
+ const runtime = {
1516
+ input: /* @__PURE__ */ __name((schema) => makeBuilder({
1517
+ ...config,
1518
+ input: schema
1519
+ }), "input"),
1520
+ model: /* @__PURE__ */ __name((id) => makeBuilder({
1521
+ ...config,
1522
+ model: id
1523
+ }), "model"),
1524
+ system: /* @__PURE__ */ __name((prompt) => makeBuilder({
1525
+ ...config,
1526
+ system: prompt
1527
+ }), "system"),
1528
+ reasoningEffort: /* @__PURE__ */ __name((effort) => makeBuilder({
1529
+ ...config,
1530
+ reasoningEffort: effort
1531
+ }), "reasoningEffort"),
1532
+ context: /* @__PURE__ */ __name((value) => makeBuilder({
1533
+ ...config,
1534
+ context: value
1535
+ }), "context"),
1536
+ tool: /* @__PURE__ */ __name((tool) => makeBuilder({
1537
+ ...config,
1538
+ tools: [
1539
+ ...config.tools ?? [],
1540
+ tool
1541
+ ]
1542
+ }), "tool"),
1543
+ use: /* @__PURE__ */ __name((preset) => preset(runtime), "use"),
1544
+ build: /* @__PURE__ */ __name(() => defineAgent(config), "build")
1545
+ };
1546
+ return runtime;
1547
+ }
1548
+ __name(makeBuilder, "makeBuilder");
1549
+ function agent() {
1550
+ return makeBuilder({});
1551
+ }
1552
+ __name(agent, "agent");
1403
1553
 
1404
1554
  // src/bridge/hitl-plugin.ts
1405
1555
  function createHitlPlugin(wiring) {
@@ -1419,7 +1569,7 @@ function createHitlPlugin(wiring) {
1419
1569
  callbackUrl: `approve/${approvalId}`,
1420
1570
  timeoutMs: opts.timeout ?? 3e5
1421
1571
  });
1422
- const approved = await wiring.awaitApproval(approvalId, opts);
1572
+ const approved = await wiring.awaitApproval(approvalId, opts, c.name);
1423
1573
  return approved ? void 0 : {
1424
1574
  block: true,
1425
1575
  message: `Tool '${c.name}' denied by human approver`
@@ -1571,6 +1721,198 @@ function streamAgentUIMessages(compiled, apiKey, input) {
1571
1721
  }
1572
1722
  __name(streamAgentUIMessages, "streamAgentUIMessages");
1573
1723
 
1724
+ // src/guardrails/types.ts
1725
+ var GuardrailViolationError = class extends Error {
1726
+ static {
1727
+ __name(this, "GuardrailViolationError");
1728
+ }
1729
+ guardName;
1730
+ phase;
1731
+ reason;
1732
+ constructor(guardName, phase, reason) {
1733
+ super(`Guardrail "${guardName}" blocked ${phase}: ${reason}`), this.guardName = guardName, this.phase = phase, this.reason = reason;
1734
+ this.name = "GuardrailViolationError";
1735
+ }
1736
+ };
1737
+ var CostBudgetExceededError = class extends Error {
1738
+ static {
1739
+ __name(this, "CostBudgetExceededError");
1740
+ }
1741
+ usedTokens;
1742
+ maxTokens;
1743
+ constructor(usedTokens, maxTokens) {
1744
+ super(`Cost budget exceeded: ${usedTokens} > ${maxTokens} tokens`), this.usedTokens = usedTokens, this.maxTokens = maxTokens;
1745
+ this.name = "CostBudgetExceededError";
1746
+ }
1747
+ };
1748
+
1749
+ // src/guardrails/detectors.ts
1750
+ function estimateTokens(text) {
1751
+ return Math.ceil(text.length / 4);
1752
+ }
1753
+ __name(estimateTokens, "estimateTokens");
1754
+ var INJECTION_PHRASES = [
1755
+ "previous instructions",
1756
+ "disregard the above",
1757
+ "you are now dan",
1758
+ "system prompt",
1759
+ "no restrictions",
1760
+ "without restrictions",
1761
+ "no rules",
1762
+ "override your"
1763
+ ];
1764
+ function normalizeForMatch(text) {
1765
+ return text.toLowerCase().replace(/\s+/g, " ");
1766
+ }
1767
+ __name(normalizeForMatch, "normalizeForMatch");
1768
+ function promptInjectionDetector(options = {}) {
1769
+ const phrases = [
1770
+ ...INJECTION_PHRASES,
1771
+ ...(options.extra ?? []).map((p) => p.toLowerCase())
1772
+ ];
1773
+ return {
1774
+ name: "prompt-injection",
1775
+ checkInput(text) {
1776
+ const normalized = normalizeForMatch(text);
1777
+ for (const phrase of phrases) {
1778
+ if (normalized.includes(phrase)) {
1779
+ return {
1780
+ action: "block",
1781
+ reason: `prompt injection phrase matched: "${phrase}"`
1782
+ };
1783
+ }
1784
+ }
1785
+ return {
1786
+ action: "allow"
1787
+ };
1788
+ }
1789
+ };
1790
+ }
1791
+ __name(promptInjectionDetector, "promptInjectionDetector");
1792
+ var CPF = /\b\d{3}\.?\d{3}\.?\d{3}-?\d{2}\b/g;
1793
+ var EMAIL = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g;
1794
+ var PHONE = /\+?\d[\d\s()-]{7,13}\d/g;
1795
+ function piiDetector(options = {}) {
1796
+ const placeholder = options.placeholder ?? "[REDACTED]";
1797
+ return {
1798
+ name: "pii",
1799
+ checkInput(text) {
1800
+ let redacted = text;
1801
+ redacted = redacted.replace(EMAIL, placeholder);
1802
+ redacted = redacted.replace(CPF, placeholder);
1803
+ redacted = redacted.replace(PHONE, placeholder);
1804
+ if (redacted === text) return {
1805
+ action: "allow"
1806
+ };
1807
+ return {
1808
+ action: "redact",
1809
+ text: redacted,
1810
+ reason: "PII detected and redacted"
1811
+ };
1812
+ }
1813
+ };
1814
+ }
1815
+ __name(piiDetector, "piiDetector");
1816
+ var OBFUSCATION_CHARS = /[\u200B-\u200D\uFEFF\u202A-\u202E\u2066-\u2069]/g;
1817
+ function unicodeNormalizer() {
1818
+ return {
1819
+ name: "unicode-normalizer",
1820
+ checkInput(text) {
1821
+ const cleaned = text.normalize("NFKC").replace(OBFUSCATION_CHARS, "");
1822
+ if (cleaned === text) return {
1823
+ action: "allow"
1824
+ };
1825
+ return {
1826
+ action: "redact",
1827
+ text: cleaned,
1828
+ reason: "obfuscation characters normalized"
1829
+ };
1830
+ }
1831
+ };
1832
+ }
1833
+ __name(unicodeNormalizer, "unicodeNormalizer");
1834
+ function costGuard(options) {
1835
+ let used = 0;
1836
+ return {
1837
+ name: "cost-guard",
1838
+ // Returns a Promise explicitly (not `async`) so a budget breach REJECTS uniformly — never a
1839
+ // sync throw — safe for direct callers and for the pipeline's `await g.checkInput()`.
1840
+ checkInput(text) {
1841
+ used += estimateTokens(text);
1842
+ if (used > options.maxTokens) {
1843
+ return Promise.reject(new CostBudgetExceededError(used, options.maxTokens));
1844
+ }
1845
+ return Promise.resolve({
1846
+ action: "allow"
1847
+ });
1848
+ }
1849
+ };
1850
+ }
1851
+ __name(costGuard, "costGuard");
1852
+ function outputModeration(options) {
1853
+ return {
1854
+ name: "output-moderation",
1855
+ async checkOutput(text) {
1856
+ const flagged = await options.moderate(text);
1857
+ return flagged ? {
1858
+ action: "block",
1859
+ reason: "output flagged by moderation predicate"
1860
+ } : {
1861
+ action: "allow"
1862
+ };
1863
+ }
1864
+ };
1865
+ }
1866
+ __name(outputModeration, "outputModeration");
1867
+
1868
+ // src/guardrails/pipeline.ts
1869
+ async function runInputGuards(text, guards) {
1870
+ let current = text;
1871
+ for (const g of guards) {
1872
+ if (!g.checkInput) continue;
1873
+ const r = await g.checkInput(current);
1874
+ if (r.action === "block") {
1875
+ throw new GuardrailViolationError(g.name, "input", r.reason ?? "blocked");
1876
+ }
1877
+ if (r.action === "redact" && r.text !== void 0) current = r.text;
1878
+ }
1879
+ return current;
1880
+ }
1881
+ __name(runInputGuards, "runInputGuards");
1882
+ async function runOutputGuards(text, guards) {
1883
+ let current = text;
1884
+ for (const g of guards) {
1885
+ if (!g.checkOutput) continue;
1886
+ const r = await g.checkOutput(current);
1887
+ if (r.action === "block") {
1888
+ throw new GuardrailViolationError(g.name, "output", r.reason ?? "blocked");
1889
+ }
1890
+ if (r.action === "redact" && r.text !== void 0) current = r.text;
1891
+ }
1892
+ return current;
1893
+ }
1894
+ __name(runOutputGuards, "runOutputGuards");
1895
+
1896
+ // src/guardrails/stream.ts
1897
+ async function* moderateOutputStream(inner, guards, extractText) {
1898
+ const hasOutputGuard = guards.some((g) => g.checkOutput != null);
1899
+ if (!hasOutputGuard) return yield* inner;
1900
+ const buffered = [];
1901
+ let accumulated = "";
1902
+ let step = await inner.next();
1903
+ while (!step.done) {
1904
+ const event = step.value;
1905
+ const text = extractText(event);
1906
+ if (text !== void 0) accumulated += text;
1907
+ buffered.push(event);
1908
+ step = await inner.next();
1909
+ }
1910
+ await runOutputGuards(accumulated, guards);
1911
+ for (const event of buffered) yield event;
1912
+ return step.value;
1913
+ }
1914
+ __name(moderateOutputStream, "moderateOutputStream");
1915
+
1574
1916
  // src/loop/compaction-strategy.ts
1575
1917
  import { compactTranscript } from "@theokit/sdk/compaction";
1576
1918
  import { z } from "zod";
@@ -1994,6 +2336,18 @@ var AgentRunner = class {
1994
2336
  * builder set `.stream(false)`, callers should use {@link run} instead.
1995
2337
  */
1996
2338
  stream(message, opts) {
2339
+ const guardrails = this.compiled.guardrails;
2340
+ if (guardrails && guardrails.length > 0) {
2341
+ const runUnguarded = /* @__PURE__ */ __name((m) => this.streamUnguarded(m, opts), "runUnguarded");
2342
+ return (/* @__PURE__ */ __name(async function* guarded() {
2343
+ const safe = await runInputGuards(message, guardrails);
2344
+ return yield* moderateOutputStream(runUnguarded(safe), guardrails, (e) => e.type === "text_delta" && typeof e.content === "string" ? e.content : void 0);
2345
+ }, "guarded"))();
2346
+ }
2347
+ return this.streamUnguarded(message, opts);
2348
+ }
2349
+ /** The core stream path, after input guardrails have run (M9). */
2350
+ streamUnguarded(message, opts) {
1997
2351
  const tools = opts.tools ? [
1998
2352
  ...opts.tools
1999
2353
  ] : this.compiled.tools;
@@ -2108,6 +2462,10 @@ function mergeTools(parentTools, subTools) {
2108
2462
  __name(mergeTools, "mergeTools");
2109
2463
  async function delegate(SubAgentClass, message, opts = {}) {
2110
2464
  const apiKey = requireApiKey(opts, SubAgentClass.name);
2465
+ const effectiveMessage = opts.onDelegationStart ? await opts.onDelegationStart({
2466
+ subAgent: SubAgentClass.name,
2467
+ input: message
2468
+ }) : message;
2111
2469
  const walk = walkAgentMetadata(SubAgentClass, []);
2112
2470
  const toolboxInstances = new Map(walk.toolboxes.map((tb) => [
2113
2471
  tb.class,
@@ -2116,7 +2474,7 @@ async function delegate(SubAgentClass, message, opts = {}) {
2116
2474
  const compiled = compileAgent(walk, toolboxInstances);
2117
2475
  const allTools = mergeTools(opts.parentTools ?? [], compiled.tools);
2118
2476
  const budget = Math.min(opts.budget ?? Infinity, opts.parentBudgetRemaining ?? Infinity);
2119
- const streamFactory = createSdkAgentStream(compiled, allTools, apiKey, {
2477
+ const streamFactory = opts.streamFactory ?? createSdkAgentStream(compiled, allTools, apiKey, {
2120
2478
  model: opts.model ?? walk.agentConfig.model,
2121
2479
  cwd: opts.cwd,
2122
2480
  plugins: opts.plugins,
@@ -2129,7 +2487,7 @@ async function delegate(SubAgentClass, message, opts = {}) {
2129
2487
  const sessionId = opts.sessionId ?? `sub-${crypto.randomUUID()}`;
2130
2488
  const loopStrategy = resolveLoopStrategy(walk.mainLoop.strategy, opts.maxIterations ?? walk.mainLoop.maxIterations);
2131
2489
  const reflection = opts.reflection ?? (loopStrategy.name === "plan-act-reflect" ? ladderReflectionStrategy : noopReflectionStrategy);
2132
- return runReflectiveLoop(streamFactory, message, sessionId, {
2490
+ const result = await runReflectiveLoop(streamFactory, effectiveMessage, sessionId, {
2133
2491
  loop: loopStrategy,
2134
2492
  reflection,
2135
2493
  budget,
@@ -2137,9 +2495,53 @@ async function delegate(SubAgentClass, message, opts = {}) {
2137
2495
  signal: opts.signal,
2138
2496
  retry: opts.retry
2139
2497
  });
2498
+ if (opts.onDelegationComplete) {
2499
+ return await opts.onDelegationComplete({
2500
+ subAgent: SubAgentClass.name,
2501
+ result
2502
+ });
2503
+ }
2504
+ return result;
2140
2505
  }
2141
2506
  __name(delegate, "delegate");
2142
2507
 
2508
+ // src/bridge/tool-hooks-plugin.ts
2509
+ function createToolHooksPlugin(hooks) {
2510
+ return {
2511
+ name: "theokit-tool-hooks",
2512
+ register(ctx) {
2513
+ const { beforeToolCall, afterToolCall, beforeLLMCall, afterLLMCall } = hooks;
2514
+ if (beforeToolCall) {
2515
+ ctx.on("pre_tool_call", (c) => beforeToolCall({
2516
+ name: c.name ?? "",
2517
+ args: c.args ?? {}
2518
+ }));
2519
+ }
2520
+ if (afterToolCall) {
2521
+ ctx.on("post_tool_call", (c) => afterToolCall({
2522
+ name: c.name ?? "",
2523
+ result: c.result
2524
+ }));
2525
+ }
2526
+ if (beforeLLMCall) {
2527
+ ctx.on("pre_llm_call", (c) => beforeLLMCall({
2528
+ agentId: c.agentId,
2529
+ runId: c.runId,
2530
+ iteration: c.iteration
2531
+ }));
2532
+ }
2533
+ if (afterLLMCall) {
2534
+ ctx.on("post_llm_call", (c) => afterLLMCall({
2535
+ agentId: c.agentId,
2536
+ runId: c.runId,
2537
+ iteration: c.iteration
2538
+ }));
2539
+ }
2540
+ }
2541
+ };
2542
+ }
2543
+ __name(createToolHooksPlugin, "createToolHooksPlugin");
2544
+
2143
2545
  // src/manifest/agent-manifest.ts
2144
2546
  function generateAgentManifest(walkResults) {
2145
2547
  return {
@@ -2295,9 +2697,22 @@ export {
2295
2697
  defineAgent,
2296
2698
  isAgentDefinition,
2297
2699
  compileAgentDefinition,
2700
+ contextualTool,
2701
+ agent,
2298
2702
  AgentDefinitionError,
2299
2703
  compileAgentModule,
2300
2704
  streamAgentUIMessages,
2705
+ GuardrailViolationError,
2706
+ CostBudgetExceededError,
2707
+ estimateTokens,
2708
+ promptInjectionDetector,
2709
+ piiDetector,
2710
+ unicodeNormalizer,
2711
+ costGuard,
2712
+ outputModeration,
2713
+ runInputGuards,
2714
+ runOutputGuards,
2715
+ moderateOutputStream,
2301
2716
  DEFAULT_KEEP_TOKENS,
2302
2717
  compactionStrategyConfigSchema,
2303
2718
  resolveCompactionStrategy,
@@ -2313,7 +2728,8 @@ export {
2313
2728
  AgentRunner,
2314
2729
  AgentRunnerBuilder,
2315
2730
  delegate,
2731
+ createToolHooksPlugin,
2316
2732
  generateAgentManifest,
2317
2733
  agentsPlugin
2318
2734
  };
2319
- //# sourceMappingURL=chunk-XCQNYAVU.js.map
2735
+ //# sourceMappingURL=chunk-BWYBOMKR.js.map