@theokit/agents 4.30.2 → 5.0.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.
@@ -455,6 +455,59 @@ function generateAgentRoutes(ctx) {
455
455
  }
456
456
  __name(generateAgentRoutes, "generateAgentRoutes");
457
457
 
458
+ // src/bridge/tool-hooks-plugin.ts
459
+ function createToolHooksPlugin(hooks) {
460
+ return {
461
+ name: "theokit-tool-hooks",
462
+ version: "1.0.0",
463
+ // `kind: 'general'` is load-bearing — without it the SDK's isCodePlugin() drops this plugin and
464
+ // no hook fires (M10/M19 latent bug, proven via a real OpenRouter run).
465
+ kind: "general",
466
+ register(ctx) {
467
+ const { beforeToolCall, afterToolCall, beforeLLMCall, afterLLMCall, processInput } = hooks;
468
+ if (beforeToolCall) {
469
+ ctx.on("pre_tool_call", (c) => beforeToolCall({
470
+ name: c.name ?? "",
471
+ args: c.args ?? {}
472
+ }));
473
+ }
474
+ if (afterToolCall) {
475
+ ctx.on("post_tool_call", (c) => afterToolCall({
476
+ name: c.name ?? "",
477
+ result: c.result
478
+ }));
479
+ }
480
+ if (beforeLLMCall) {
481
+ ctx.on("pre_llm_call", (c) => beforeLLMCall({
482
+ agentId: c.agentId,
483
+ runId: c.runId,
484
+ iteration: c.iteration
485
+ }));
486
+ }
487
+ if (afterLLMCall) {
488
+ ctx.on("post_llm_call", (c) => afterLLMCall({
489
+ agentId: c.agentId,
490
+ runId: c.runId,
491
+ iteration: c.iteration
492
+ }));
493
+ }
494
+ if (processInput) {
495
+ ctx.on("pre_user_send", async (c) => {
496
+ const injected = await processInput({
497
+ prompt: c.prompt ?? "",
498
+ agentId: c.agentId,
499
+ runId: c.runId
500
+ });
501
+ return injected !== void 0 && injected.length > 0 ? {
502
+ recalledContext: injected
503
+ } : void 0;
504
+ });
505
+ }
506
+ }
507
+ };
508
+ }
509
+ __name(createToolHooksPlugin, "createToolHooksPlugin");
510
+
458
511
  // src/bridge/event-translator.ts
459
512
  function asString(value, fallback) {
460
513
  if (typeof value === "string") return value;
@@ -766,6 +819,116 @@ function debugLog(marker, data) {
766
819
  }
767
820
  __name(debugLog, "debugLog");
768
821
 
822
+ // src/bridge/hitl-plugin.ts
823
+ function createHitlPlugin(wiring) {
824
+ return {
825
+ name: "theokit-hitl",
826
+ version: "1.0.0",
827
+ // `kind: 'general'` is load-bearing — without it the SDK's isCodePlugin() drops this plugin and
828
+ // the HITL veto never fires (the run would proceed WITHOUT waiting for human approval).
829
+ kind: "general",
830
+ register(ctx) {
831
+ ctx.on("pre_tool_call", async (c) => {
832
+ const opts = wiring.gated.get(c.name);
833
+ if (!opts) return void 0;
834
+ const approvalId = crypto.randomUUID();
835
+ wiring.emit({
836
+ type: "approval_required",
837
+ callId: approvalId,
838
+ toolName: c.name,
839
+ question: opts.question,
840
+ input: c.args,
841
+ callbackUrl: `approve/${approvalId}`,
842
+ timeoutMs: opts.timeout ?? 3e5,
843
+ // M20 — carry the declared custom-payload schema so the UI knows what to collect.
844
+ ...opts.payloadSchema !== void 0 ? {
845
+ payloadSchema: opts.payloadSchema
846
+ } : {}
847
+ });
848
+ const raw = await wiring.awaitApproval(approvalId, opts, c.name);
849
+ const decision = typeof raw === "boolean" ? {
850
+ approved: raw
851
+ } : raw;
852
+ if (decision.approved) return void 0;
853
+ let message = `Tool '${c.name}' denied by human approver`;
854
+ if (decision.reason) message += `: ${decision.reason}`;
855
+ if (decision.payload !== void 0) {
856
+ message += ` (payload: ${JSON.stringify(decision.payload)})`;
857
+ }
858
+ return {
859
+ block: true,
860
+ message
861
+ };
862
+ });
863
+ }
864
+ };
865
+ }
866
+ __name(createHitlPlugin, "createHitlPlugin");
867
+
868
+ // src/bridge/approval-posture.ts
869
+ function razaoDe(postura) {
870
+ return postura.kind === "interactive" ? "human approver on this surface" : postura.reason;
871
+ }
872
+ __name(razaoDe, "razaoDe");
873
+ function aplicarPostura(extra, m8, postura, gated) {
874
+ const daPostura = pluginsDaPostura(postura, gated);
875
+ if (daPostura.length === 0) return;
876
+ const atuais = extra.plugins ?? m8.plugins;
877
+ if (atuais !== void 0 && !Array.isArray(atuais)) {
878
+ throw new Error(`[@theokit/agents] approval posture "${postura.kind}" needs to install a plugin, but \`plugins\` was supplied in the legacy object form, which cannot carry both. Pass \`plugins\` as an array so the approval gate is not dropped.`);
879
+ }
880
+ extra.plugins = [
881
+ ...atuais ?? [],
882
+ ...daPostura
883
+ ];
884
+ }
885
+ __name(aplicarPostura, "aplicarPostura");
886
+ function pluginsDaPostura(postura, gated) {
887
+ debugLog("[theokit] approval posture", {
888
+ kind: postura.kind,
889
+ reason: razaoDe(postura)
890
+ });
891
+ if (gated === void 0 || gated.size === 0) return [];
892
+ switch (postura.kind) {
893
+ case "interactive":
894
+ return [
895
+ createHitlPlugin({
896
+ gated,
897
+ emit: postura.emit,
898
+ awaitApproval: postura.awaitApproval
899
+ })
900
+ ];
901
+ case "auto-approve":
902
+ return [
903
+ createToolHooksPlugin({
904
+ beforeToolCall: /* @__PURE__ */ __name((ctx) => {
905
+ if (gated.has(ctx.name)) {
906
+ debugLog("[theokit] gated tool auto-approved", {
907
+ tool: ctx.name,
908
+ reason: postura.reason
909
+ });
910
+ }
911
+ return void 0;
912
+ }, "beforeToolCall")
913
+ })
914
+ ];
915
+ case "auto-reject":
916
+ return [
917
+ createToolHooksPlugin({
918
+ // Só as tools GATEADAS são recusadas: a postura descreve o gate, não um bloqueio universal.
919
+ // Recusar tudo quebraria todo agente que tem uma tool livre ao lado de uma gateada.
920
+ beforeToolCall: /* @__PURE__ */ __name((ctx) => gated.has(ctx.name) ? {
921
+ block: true,
922
+ message: `Tool '${ctx.name}' requires human approval, and this surface has no approver (approval posture: auto-reject \u2014 ${postura.reason}). Refused (fail-closed).`
923
+ } : void 0, "beforeToolCall")
924
+ })
925
+ ];
926
+ case "owned-by-surface":
927
+ return [];
928
+ }
929
+ }
930
+ __name(pluginsDaPostura, "pluginsDaPostura");
931
+
769
932
  // src/bridge/definicao-ou-thunk.ts
770
933
  function projetar(def, overrides) {
771
934
  const compiled = compileAgentDefinition(def);
@@ -1342,6 +1505,7 @@ function toAgentFactory(def, opts) {
1342
1505
  baseDir: overrides.baseDir
1343
1506
  };
1344
1507
  const extra = buildExtraCreateOptions(overrides, compiled);
1508
+ aplicarPostura(extra, m8, opts.approvals, compiled.hitl);
1345
1509
  const agent = await rt.Agent.getOrCreate(sessionId, {
1346
1510
  apiKey: await resolverApiKey(opts.apiKey),
1347
1511
  model: buildModelSelection(model, reasoningEffort),
@@ -2098,52 +2262,6 @@ var AgentBuilder = {
2098
2262
  }
2099
2263
  };
2100
2264
 
2101
- // src/bridge/hitl-plugin.ts
2102
- function createHitlPlugin(wiring) {
2103
- return {
2104
- name: "theokit-hitl",
2105
- version: "1.0.0",
2106
- // `kind: 'general'` is load-bearing — without it the SDK's isCodePlugin() drops this plugin and
2107
- // the HITL veto never fires (the run would proceed WITHOUT waiting for human approval).
2108
- kind: "general",
2109
- register(ctx) {
2110
- ctx.on("pre_tool_call", async (c) => {
2111
- const opts = wiring.gated.get(c.name);
2112
- if (!opts) return void 0;
2113
- const approvalId = crypto.randomUUID();
2114
- wiring.emit({
2115
- type: "approval_required",
2116
- callId: approvalId,
2117
- toolName: c.name,
2118
- question: opts.question,
2119
- input: c.args,
2120
- callbackUrl: `approve/${approvalId}`,
2121
- timeoutMs: opts.timeout ?? 3e5,
2122
- // M20 — carry the declared custom-payload schema so the UI knows what to collect.
2123
- ...opts.payloadSchema !== void 0 ? {
2124
- payloadSchema: opts.payloadSchema
2125
- } : {}
2126
- });
2127
- const raw = await wiring.awaitApproval(approvalId, opts, c.name);
2128
- const decision = typeof raw === "boolean" ? {
2129
- approved: raw
2130
- } : raw;
2131
- if (decision.approved) return void 0;
2132
- let message = `Tool '${c.name}' denied by human approver`;
2133
- if (decision.reason) message += `: ${decision.reason}`;
2134
- if (decision.payload !== void 0) {
2135
- message += ` (payload: ${JSON.stringify(decision.payload)})`;
2136
- }
2137
- return {
2138
- block: true,
2139
- message
2140
- };
2141
- });
2142
- }
2143
- };
2144
- }
2145
- __name(createHitlPlugin, "createHitlPlugin");
2146
-
2147
2265
  // src/bridge/agent-endpoint.ts
2148
2266
  var AgentDefinitionError = class extends Error {
2149
2267
  static {
@@ -3140,59 +3258,6 @@ async function delegate(spec, message, opts = {}) {
3140
3258
  }
3141
3259
  __name(delegate, "delegate");
3142
3260
 
3143
- // src/bridge/tool-hooks-plugin.ts
3144
- function createToolHooksPlugin(hooks) {
3145
- return {
3146
- name: "theokit-tool-hooks",
3147
- version: "1.0.0",
3148
- // `kind: 'general'` is load-bearing — without it the SDK's isCodePlugin() drops this plugin and
3149
- // no hook fires (M10/M19 latent bug, proven via a real OpenRouter run).
3150
- kind: "general",
3151
- register(ctx) {
3152
- const { beforeToolCall, afterToolCall, beforeLLMCall, afterLLMCall, processInput } = hooks;
3153
- if (beforeToolCall) {
3154
- ctx.on("pre_tool_call", (c) => beforeToolCall({
3155
- name: c.name ?? "",
3156
- args: c.args ?? {}
3157
- }));
3158
- }
3159
- if (afterToolCall) {
3160
- ctx.on("post_tool_call", (c) => afterToolCall({
3161
- name: c.name ?? "",
3162
- result: c.result
3163
- }));
3164
- }
3165
- if (beforeLLMCall) {
3166
- ctx.on("pre_llm_call", (c) => beforeLLMCall({
3167
- agentId: c.agentId,
3168
- runId: c.runId,
3169
- iteration: c.iteration
3170
- }));
3171
- }
3172
- if (afterLLMCall) {
3173
- ctx.on("post_llm_call", (c) => afterLLMCall({
3174
- agentId: c.agentId,
3175
- runId: c.runId,
3176
- iteration: c.iteration
3177
- }));
3178
- }
3179
- if (processInput) {
3180
- ctx.on("pre_user_send", async (c) => {
3181
- const injected = await processInput({
3182
- prompt: c.prompt ?? "",
3183
- agentId: c.agentId,
3184
- runId: c.runId
3185
- });
3186
- return injected !== void 0 && injected.length > 0 ? {
3187
- recalledContext: injected
3188
- } : void 0;
3189
- });
3190
- }
3191
- }
3192
- };
3193
- }
3194
- __name(createToolHooksPlugin, "createToolHooksPlugin");
3195
-
3196
3261
  // src/bridge/api-error-handler.ts
3197
3262
  var DEFAULT_MAX_ATTEMPTS = 3;
3198
3263
  async function runWithApiErrorHandling(thunk, policy) {
@@ -3497,6 +3562,7 @@ export {
3497
3562
  isError,
3498
3563
  isApprovalRequired,
3499
3564
  generateAgentRoutes,
3565
+ createToolHooksPlugin,
3500
3566
  translateSdkEvent,
3501
3567
  buildModelSelection,
3502
3568
  createThinkTagExtractor,
@@ -3538,7 +3604,6 @@ export {
3538
3604
  GoalRunner,
3539
3605
  JudgeCredentialError,
3540
3606
  delegate,
3541
- createToolHooksPlugin,
3542
3607
  runWithApiErrorHandling,
3543
3608
  createApiErrorHandler,
3544
3609
  delegateBackground,
@@ -3549,4 +3614,4 @@ export {
3549
3614
  generateAgentManifest,
3550
3615
  agentsPlugin
3551
3616
  };
3552
- //# sourceMappingURL=chunk-GGB5WXHS.js.map
3617
+ //# sourceMappingURL=chunk-JXR45RAW.js.map