@theokit/agents 4.30.1 → 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);
@@ -786,6 +949,20 @@ function resolverProjecao(def, overrides) {
786
949
  }
787
950
  __name(resolverProjecao, "resolverProjecao");
788
951
 
952
+ // src/bridge/erro-do-sdk.ts
953
+ function eventoDeErroDoSdk(err) {
954
+ const sdkErr = err;
955
+ return {
956
+ type: "error",
957
+ code: sdkErr.code ?? "SDK_ERROR",
958
+ message: err instanceof Error ? err.message : "SDK agent error",
959
+ // O SDK computa `isRetryable` por classe de erro na construção; fixá-lo em `false` aqui
960
+ // contradizia o próprio erro.
961
+ retryable: sdkErr.isRetryable === true
962
+ };
963
+ }
964
+ __name(eventoDeErroDoSdk, "eventoDeErroDoSdk");
965
+
789
966
  // src/bridge/sdk-adapter-create-options.ts
790
967
  function assembleM8CreateOptions(compiled) {
791
968
  const options = {};
@@ -1189,18 +1366,6 @@ function buildSdkTools(compiledTools, defineTool, extraSdkTools = [], runContext
1189
1366
  }
1190
1367
  __name(buildSdkTools, "buildSdkTools");
1191
1368
  var resolverApiKey = /* @__PURE__ */ __name(async (k) => typeof k === "function" ? await k() : k, "resolverApiKey");
1192
- function eventoDeErroDoSdk(err) {
1193
- const sdkErr = err;
1194
- return {
1195
- type: "error",
1196
- code: sdkErr.code ?? "SDK_ERROR",
1197
- message: err instanceof Error ? err.message : "SDK agent error",
1198
- // O SDK computa `isRetryable` por classe de erro na construção; fixá-lo em `false` aqui
1199
- // contradizia o próprio erro.
1200
- retryable: sdkErr.isRetryable === true
1201
- };
1202
- }
1203
- __name(eventoDeErroDoSdk, "eventoDeErroDoSdk");
1204
1369
  function createSdkAgentStream(compiled, compiledTools, apiKey, overrides = {}) {
1205
1370
  const model = overrides.model ?? compiled.model ?? "openai/gpt-4o-mini";
1206
1371
  const reasoningEffort = overrides.reasoningEffort ?? compiled.reasoningEffort;
@@ -1340,6 +1505,7 @@ function toAgentFactory(def, opts) {
1340
1505
  baseDir: overrides.baseDir
1341
1506
  };
1342
1507
  const extra = buildExtraCreateOptions(overrides, compiled);
1508
+ aplicarPostura(extra, m8, opts.approvals, compiled.hitl);
1343
1509
  const agent = await rt.Agent.getOrCreate(sessionId, {
1344
1510
  apiKey: await resolverApiKey(opts.apiKey),
1345
1511
  model: buildModelSelection(model, reasoningEffort),
@@ -2096,52 +2262,6 @@ var AgentBuilder = {
2096
2262
  }
2097
2263
  };
2098
2264
 
2099
- // src/bridge/hitl-plugin.ts
2100
- function createHitlPlugin(wiring) {
2101
- return {
2102
- name: "theokit-hitl",
2103
- version: "1.0.0",
2104
- // `kind: 'general'` is load-bearing — without it the SDK's isCodePlugin() drops this plugin and
2105
- // the HITL veto never fires (the run would proceed WITHOUT waiting for human approval).
2106
- kind: "general",
2107
- register(ctx) {
2108
- ctx.on("pre_tool_call", async (c) => {
2109
- const opts = wiring.gated.get(c.name);
2110
- if (!opts) return void 0;
2111
- const approvalId = crypto.randomUUID();
2112
- wiring.emit({
2113
- type: "approval_required",
2114
- callId: approvalId,
2115
- toolName: c.name,
2116
- question: opts.question,
2117
- input: c.args,
2118
- callbackUrl: `approve/${approvalId}`,
2119
- timeoutMs: opts.timeout ?? 3e5,
2120
- // M20 — carry the declared custom-payload schema so the UI knows what to collect.
2121
- ...opts.payloadSchema !== void 0 ? {
2122
- payloadSchema: opts.payloadSchema
2123
- } : {}
2124
- });
2125
- const raw = await wiring.awaitApproval(approvalId, opts, c.name);
2126
- const decision = typeof raw === "boolean" ? {
2127
- approved: raw
2128
- } : raw;
2129
- if (decision.approved) return void 0;
2130
- let message = `Tool '${c.name}' denied by human approver`;
2131
- if (decision.reason) message += `: ${decision.reason}`;
2132
- if (decision.payload !== void 0) {
2133
- message += ` (payload: ${JSON.stringify(decision.payload)})`;
2134
- }
2135
- return {
2136
- block: true,
2137
- message
2138
- };
2139
- });
2140
- }
2141
- };
2142
- }
2143
- __name(createHitlPlugin, "createHitlPlugin");
2144
-
2145
2265
  // src/bridge/agent-endpoint.ts
2146
2266
  var AgentDefinitionError = class extends Error {
2147
2267
  static {
@@ -3138,59 +3258,6 @@ async function delegate(spec, message, opts = {}) {
3138
3258
  }
3139
3259
  __name(delegate, "delegate");
3140
3260
 
3141
- // src/bridge/tool-hooks-plugin.ts
3142
- function createToolHooksPlugin(hooks) {
3143
- return {
3144
- name: "theokit-tool-hooks",
3145
- version: "1.0.0",
3146
- // `kind: 'general'` is load-bearing — without it the SDK's isCodePlugin() drops this plugin and
3147
- // no hook fires (M10/M19 latent bug, proven via a real OpenRouter run).
3148
- kind: "general",
3149
- register(ctx) {
3150
- const { beforeToolCall, afterToolCall, beforeLLMCall, afterLLMCall, processInput } = hooks;
3151
- if (beforeToolCall) {
3152
- ctx.on("pre_tool_call", (c) => beforeToolCall({
3153
- name: c.name ?? "",
3154
- args: c.args ?? {}
3155
- }));
3156
- }
3157
- if (afterToolCall) {
3158
- ctx.on("post_tool_call", (c) => afterToolCall({
3159
- name: c.name ?? "",
3160
- result: c.result
3161
- }));
3162
- }
3163
- if (beforeLLMCall) {
3164
- ctx.on("pre_llm_call", (c) => beforeLLMCall({
3165
- agentId: c.agentId,
3166
- runId: c.runId,
3167
- iteration: c.iteration
3168
- }));
3169
- }
3170
- if (afterLLMCall) {
3171
- ctx.on("post_llm_call", (c) => afterLLMCall({
3172
- agentId: c.agentId,
3173
- runId: c.runId,
3174
- iteration: c.iteration
3175
- }));
3176
- }
3177
- if (processInput) {
3178
- ctx.on("pre_user_send", async (c) => {
3179
- const injected = await processInput({
3180
- prompt: c.prompt ?? "",
3181
- agentId: c.agentId,
3182
- runId: c.runId
3183
- });
3184
- return injected !== void 0 && injected.length > 0 ? {
3185
- recalledContext: injected
3186
- } : void 0;
3187
- });
3188
- }
3189
- }
3190
- };
3191
- }
3192
- __name(createToolHooksPlugin, "createToolHooksPlugin");
3193
-
3194
3261
  // src/bridge/api-error-handler.ts
3195
3262
  var DEFAULT_MAX_ATTEMPTS = 3;
3196
3263
  async function runWithApiErrorHandling(thunk, policy) {
@@ -3495,6 +3562,7 @@ export {
3495
3562
  isError,
3496
3563
  isApprovalRequired,
3497
3564
  generateAgentRoutes,
3565
+ createToolHooksPlugin,
3498
3566
  translateSdkEvent,
3499
3567
  buildModelSelection,
3500
3568
  createThinkTagExtractor,
@@ -3536,7 +3604,6 @@ export {
3536
3604
  GoalRunner,
3537
3605
  JudgeCredentialError,
3538
3606
  delegate,
3539
- createToolHooksPlugin,
3540
3607
  runWithApiErrorHandling,
3541
3608
  createApiErrorHandler,
3542
3609
  delegateBackground,
@@ -3547,4 +3614,4 @@ export {
3547
3614
  generateAgentManifest,
3548
3615
  agentsPlugin
3549
3616
  };
3550
- //# sourceMappingURL=chunk-LWF36KFK.js.map
3617
+ //# sourceMappingURL=chunk-JXR45RAW.js.map