@anvia/core 0.11.3 → 0.12.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 (56) hide show
  1. package/dist/agent/index.d.ts +11 -8
  2. package/dist/agent/index.js +10 -9
  3. package/dist/{agent-Bcpuodu2.d.ts → agent-BWF8_O8k.d.ts} +14 -5
  4. package/dist/{chunk-MLMXQ2OV.js → chunk-4AJJIIAQ.js} +9 -7
  5. package/dist/chunk-4AJJIIAQ.js.map +1 -0
  6. package/dist/{chunk-7CQAERL3.js → chunk-KTTIPWE7.js} +457 -107
  7. package/dist/chunk-KTTIPWE7.js.map +1 -0
  8. package/dist/{chunk-2GXGB6U5.js → chunk-MIJUAWHU.js} +4 -4
  9. package/dist/{chunk-5EDHXYH5.js → chunk-PGFYN5ZX.js} +12 -7
  10. package/dist/chunk-PGFYN5ZX.js.map +1 -0
  11. package/dist/{chunk-FV5B4SGK.js → chunk-R7F2JF7J.js} +6 -6
  12. package/dist/chunk-R7F2JF7J.js.map +1 -0
  13. package/dist/{chunk-NI637AGP.js → chunk-TIH4QM55.js} +12 -3
  14. package/dist/chunk-TIH4QM55.js.map +1 -0
  15. package/dist/chunk-YRERPIA5.js +451 -0
  16. package/dist/chunk-YRERPIA5.js.map +1 -0
  17. package/dist/{chunk-V3WTT7TE.js → chunk-ZGIE73BH.js} +2 -2
  18. package/dist/evals/index.d.ts +6 -5
  19. package/dist/evals/index.js +14 -13
  20. package/dist/evals/index.js.map +1 -1
  21. package/dist/extractor/index.d.ts +6 -5
  22. package/dist/extractor/index.js +11 -10
  23. package/dist/guardrails/index.d.ts +211 -0
  24. package/dist/guardrails/index.js +35 -0
  25. package/dist/guardrails/index.js.map +1 -0
  26. package/dist/{index-CD9jb9Or.d.ts → index-DsWWqP0Q.d.ts} +8 -1
  27. package/dist/index.d.ts +9 -8
  28. package/dist/index.js +34 -16
  29. package/dist/internal/agent.d.ts +6 -5
  30. package/dist/internal/agent.js +9 -8
  31. package/dist/mcp/index.d.ts +4 -3
  32. package/dist/{middleware-ByyL6Rj0.d.ts → middleware-BTR0eRtx.d.ts} +2 -2
  33. package/dist/observability/index.d.ts +3 -2
  34. package/dist/pipeline/index.d.ts +6 -5
  35. package/dist/pipeline/index.js +3 -3
  36. package/dist/request/index.d.ts +6 -5
  37. package/dist/request/index.js +8 -7
  38. package/dist/skills/index.d.ts +4 -3
  39. package/dist/skills/index.js +6 -6
  40. package/dist/{think-tool-B065hm73.d.ts → think-tool-Bn3HHu_z.d.ts} +4 -1
  41. package/dist/tool/index.d.ts +5 -4
  42. package/dist/tool/index.js +5 -5
  43. package/dist/{tool-B8K543oQ.d.ts → tool-DGELXD2z.d.ts} +3 -0
  44. package/dist/{types-Pl4PFQWL.d.ts → types-9VPKg7ih.d.ts} +1 -1
  45. package/dist/{types-BzUuhjKr.d.ts → types-Bx_ZtjPi.d.ts} +1 -1
  46. package/dist/{types-7F_IKQQW.d.ts → types-Dc83Qzch.d.ts} +1 -1
  47. package/dist/vector-store/index.d.ts +4 -3
  48. package/dist/vector-store/index.js +3 -3
  49. package/package.json +6 -2
  50. package/dist/chunk-5EDHXYH5.js.map +0 -1
  51. package/dist/chunk-7CQAERL3.js.map +0 -1
  52. package/dist/chunk-FV5B4SGK.js.map +0 -1
  53. package/dist/chunk-MLMXQ2OV.js.map +0 -1
  54. package/dist/chunk-NI637AGP.js.map +0 -1
  55. /package/dist/{chunk-2GXGB6U5.js.map → chunk-MIJUAWHU.js.map} +0 -0
  56. /package/dist/{chunk-V3WTT7TE.js.map → chunk-ZGIE73BH.js.map} +0 -0
@@ -4,15 +4,20 @@ import {
4
4
  import {
5
5
  parseToolArgs,
6
6
  toolResultContentToText
7
- } from "./chunk-FV5B4SGK.js";
7
+ } from "./chunk-R7F2JF7J.js";
8
8
  import {
9
- mapWithConcurrency
10
- } from "./chunk-OIMLU4SF.js";
9
+ runControl,
10
+ toolCallControl
11
+ } from "./chunk-NPZDYOE6.js";
12
+ import {
13
+ compact
14
+ } from "./chunk-MMHG7WAM.js";
11
15
  import {
12
16
  CompletionRequestBuilder,
13
17
  isStreamingCompletionModel
14
18
  } from "./chunk-SRBW3LD7.js";
15
19
  import {
20
+ AssistantContent,
16
21
  Message,
17
22
  ToolContent,
18
23
  Usage,
@@ -20,12 +25,16 @@ import {
20
25
  textFromAssistantContent
21
26
  } from "./chunk-5LFGEMIW.js";
22
27
  import {
23
- runControl,
24
- toolCallControl
25
- } from "./chunk-NPZDYOE6.js";
28
+ mapWithConcurrency
29
+ } from "./chunk-OIMLU4SF.js";
26
30
  import {
27
- compact
28
- } from "./chunk-MMHG7WAM.js";
31
+ appendGuardrailPolicies,
32
+ hasEnforcedOutputGuardrails,
33
+ runInputGuardrails,
34
+ runOutputGuardrails,
35
+ runToolGuardrails,
36
+ runToolResultGuardrails
37
+ } from "./chunk-YRERPIA5.js";
29
38
 
30
39
  // src/request/errors.ts
31
40
  var MaxTurnsError = class extends Error {
@@ -540,22 +549,26 @@ function isGenerationDeltaEvent(type) {
540
549
  // src/internal/prompt-runtime/tool-execution.ts
541
550
  var MCP_TOOL_METADATA_KEY = /* @__PURE__ */ Symbol.for("anvia.mcp.tool.metadata");
542
551
  var ToolCallExecutor = class {
543
- constructor(agent, activeHook, approvals, runContext, concurrency, requestMiddlewares, cancel) {
552
+ constructor(agent, activeHook, approvals, guardrails, runContext, concurrency, requestMiddlewares, cancel, onGuardrailDecision) {
544
553
  this.agent = agent;
545
554
  this.activeHook = activeHook;
546
555
  this.approvals = approvals;
556
+ this.guardrails = guardrails;
547
557
  this.runContext = runContext;
548
558
  this.concurrency = concurrency;
549
559
  this.requestMiddlewares = requestMiddlewares;
550
560
  this.cancel = cancel;
561
+ this.onGuardrailDecision = onGuardrailDecision;
551
562
  }
552
563
  agent;
553
564
  activeHook;
554
565
  approvals;
566
+ guardrails;
555
567
  runContext;
556
568
  concurrency;
557
569
  requestMiddlewares;
558
570
  cancel;
571
+ onGuardrailDecision;
559
572
  async execute(toolCalls, onResult, onStreamEvent, observation) {
560
573
  return mapWithConcurrency(toolCalls, this.concurrency, async (toolCall) => {
561
574
  const args = JSON.stringify(toolCall.function.arguments ?? {});
@@ -585,6 +598,9 @@ var ToolCallExecutor = class {
585
598
  toolMetadata
586
599
  })
587
600
  );
601
+ let output;
602
+ let skipped = false;
603
+ let effectiveArgs = args;
588
604
  const callAction = await this.activeHook?.onToolCall?.({
589
605
  ...hookArgs,
590
606
  tool: toolCallControl
@@ -595,14 +611,11 @@ var ToolCallExecutor = class {
595
611
  observation?.turn,
596
612
  toolCall,
597
613
  internalCallId,
598
- args,
614
+ effectiveArgs,
599
615
  callAction.reason
600
616
  );
601
617
  throw this.cancel(callAction.reason);
602
618
  }
603
- let output;
604
- let skipped = false;
605
- let effectiveArgs = args;
606
619
  if (callAction?.type === "skip") {
607
620
  output = callAction.reason;
608
621
  skipped = true;
@@ -614,8 +627,50 @@ var ToolCallExecutor = class {
614
627
  turn: observation?.turn ?? 0,
615
628
  originalArgs: args
616
629
  });
617
- const effectiveHookArgs = { ...hookArgs, args: effectiveArgs };
618
- approvalDecision = callAction?.type === "approval_request" ? await this.requestApproval(tool, effectiveHookArgs, callAction) : await this.evaluateToolApproval(tool, effectiveHookArgs) ?? { approved: true };
630
+ hookArgs.args = effectiveArgs;
631
+ const inputGuardrailResult = await runToolGuardrails(
632
+ this.guardrails,
633
+ tool?.inputGuardrails ?? [],
634
+ toolGuardrailContext(
635
+ tool,
636
+ hookArgs,
637
+ this.agent,
638
+ this.runContext,
639
+ observation?.turn ?? 0
640
+ )
641
+ );
642
+ await this.recordGuardrailDecisions(inputGuardrailResult.decisions);
643
+ effectiveArgs = inputGuardrailResult.rawArgs;
644
+ hookArgs.args = effectiveArgs;
645
+ if (inputGuardrailResult.blocked) {
646
+ output = inputGuardrailResult.message ?? "Tool call blocked by guardrail.";
647
+ skipped = true;
648
+ } else {
649
+ approvalDecision = inputGuardrailResult.approval !== void 0 ? await this.requestApproval(
650
+ tool,
651
+ hookArgs,
652
+ compact({
653
+ reason: inputGuardrailResult.approval.reason,
654
+ rejectMessage: inputGuardrailResult.approval.rejectMessage
655
+ })
656
+ ) : callAction?.type === "approval_request" ? await this.requestApproval(tool, hookArgs, callAction) : await this.evaluateToolApproval(tool, hookArgs) ?? { approved: true };
657
+ if (!approvalDecision.approved) {
658
+ output = approvalDecision.result;
659
+ skipped = true;
660
+ } else {
661
+ output = await this.runApprovedToolCall(
662
+ toolCall,
663
+ hookArgs,
664
+ effectiveArgs,
665
+ args,
666
+ toolObservers,
667
+ observation,
668
+ onStreamEvent,
669
+ false
670
+ );
671
+ effectiveArgs = hookArgs.args;
672
+ }
673
+ }
619
674
  } catch (error) {
620
675
  await recordToolError(
621
676
  toolObservers,
@@ -627,52 +682,6 @@ var ToolCallExecutor = class {
627
682
  );
628
683
  throw error;
629
684
  }
630
- if (!approvalDecision.approved) {
631
- output = approvalDecision.result;
632
- skipped = true;
633
- } else {
634
- try {
635
- output = await this.agent.callTool(toolCall.function.name, effectiveArgs, {
636
- emitStreamEvent: async (event) => {
637
- await toolObservers?.streamEvent(
638
- compact({
639
- turn: observation?.turn ?? 0,
640
- toolCall,
641
- toolName: toolCall.function.name,
642
- internalCallId,
643
- args: effectiveArgs,
644
- toolCallId: toolCall.callId,
645
- event
646
- })
647
- );
648
- const payload = agentToolEventPayload(toolCall, internalCallId, event);
649
- if (payload !== void 0) {
650
- onStreamEvent?.(payload);
651
- }
652
- }
653
- });
654
- } catch (error) {
655
- const errorAction = await this.activeHook?.onToolError?.({
656
- ...hookArgs,
657
- args: effectiveArgs,
658
- error,
659
- run: runControl
660
- });
661
- await toolObservers?.error({
662
- turn: observation?.turn ?? 0,
663
- toolCall,
664
- toolName: toolCall.function.name,
665
- internalCallId,
666
- args: effectiveArgs,
667
- ...toolCall.callId !== void 0 && { toolCallId: toolCall.callId },
668
- error
669
- });
670
- if (errorAction?.type === "terminate") {
671
- throw this.cancel(errorAction.reason);
672
- }
673
- output = error instanceof Error ? error.toString() : String(error);
674
- }
675
- }
676
685
  }
677
686
  let result = toolOutputToText(output);
678
687
  let structuredResult = toolOutputToStructuredResult(output);
@@ -692,6 +701,29 @@ var ToolCallExecutor = class {
692
701
  structuredResult = toolOutputToStructuredResult(middlewareReplacement);
693
702
  }
694
703
  }
704
+ const resultGuardrailResult = await runToolResultGuardrails(
705
+ this.guardrails,
706
+ tool?.outputGuardrails ?? [],
707
+ toolResultGuardrailContext(
708
+ tool,
709
+ hookArgs,
710
+ result,
711
+ structuredResult,
712
+ this.agent,
713
+ this.runContext,
714
+ observation?.turn ?? 0
715
+ )
716
+ );
717
+ await this.recordGuardrailDecisions(resultGuardrailResult.decisions);
718
+ if (resultGuardrailResult.blocked) {
719
+ output = resultGuardrailResult.message ?? "Tool result blocked by guardrail.";
720
+ result = toolOutputToText(output);
721
+ structuredResult = toolOutputToStructuredResult(output);
722
+ } else if (resultGuardrailResult.result !== result || resultGuardrailResult.structuredResult !== structuredResult) {
723
+ output = resultGuardrailResult.structuredResult ?? resultGuardrailResult.result;
724
+ result = resultGuardrailResult.result;
725
+ structuredResult = resultGuardrailResult.structuredResult;
726
+ }
695
727
  const resultAction = await this.activeHook?.onToolResult?.({
696
728
  ...hookArgs,
697
729
  args: effectiveArgs,
@@ -728,6 +760,61 @@ var ToolCallExecutor = class {
728
760
  return ToolContent.toolResult(toolCall.id, output, toolCall.callId);
729
761
  });
730
762
  }
763
+ async runApprovedToolCall(toolCall, hookArgs, effectiveArgs, originalArgs, toolObservers, observation, onStreamEvent, applyInputMiddleware = true) {
764
+ const middlewareArgs = applyInputMiddleware ? await this.runToolInputMiddlewares({
765
+ ...hookArgs,
766
+ args: effectiveArgs,
767
+ turn: observation?.turn ?? 0,
768
+ originalArgs
769
+ }) : effectiveArgs;
770
+ hookArgs.args = middlewareArgs;
771
+ try {
772
+ return await this.agent.callTool(toolCall.function.name, middlewareArgs, {
773
+ emitStreamEvent: async (event) => {
774
+ await toolObservers?.streamEvent(
775
+ compact({
776
+ turn: observation?.turn ?? 0,
777
+ toolCall,
778
+ toolName: toolCall.function.name,
779
+ internalCallId: hookArgs.internalCallId,
780
+ args: middlewareArgs,
781
+ toolCallId: toolCall.callId,
782
+ event
783
+ })
784
+ );
785
+ const payload = agentToolEventPayload(toolCall, hookArgs.internalCallId, event);
786
+ if (payload !== void 0) {
787
+ onStreamEvent?.(payload);
788
+ }
789
+ }
790
+ });
791
+ } catch (error) {
792
+ const errorAction = await this.activeHook?.onToolError?.({
793
+ ...hookArgs,
794
+ args: middlewareArgs,
795
+ error,
796
+ run: runControl
797
+ });
798
+ await toolObservers?.error({
799
+ turn: observation?.turn ?? 0,
800
+ toolCall,
801
+ toolName: toolCall.function.name,
802
+ internalCallId: hookArgs.internalCallId,
803
+ args: middlewareArgs,
804
+ ...toolCall.callId !== void 0 && { toolCallId: toolCall.callId },
805
+ error
806
+ });
807
+ if (errorAction?.type === "terminate") {
808
+ throw this.cancel(errorAction.reason);
809
+ }
810
+ return error instanceof Error ? error.toString() : String(error);
811
+ }
812
+ }
813
+ async recordGuardrailDecisions(decisions) {
814
+ for (const decision of decisions) {
815
+ await this.onGuardrailDecision?.(decision);
816
+ }
817
+ }
731
818
  async runToolResultMiddlewares(args) {
732
819
  let result = args.result;
733
820
  let structuredResult = args.structuredResult;
@@ -829,6 +916,55 @@ function approvalContext(tool, hookArgs, agent, run) {
829
916
  })
830
917
  });
831
918
  }
919
+ function toolGuardrailContext(tool, hookArgs, agent, run, turn) {
920
+ const parsedArgs = parseGuardrailContextArgs(tool, hookArgs.args);
921
+ return compact({
922
+ toolName: hookArgs.toolName,
923
+ args: parsedArgs,
924
+ rawArgs: hookArgs.args,
925
+ toolCallId: hookArgs.toolCallId,
926
+ internalCallId: hookArgs.internalCallId,
927
+ turn,
928
+ run: guardrailRunContext(agent, run)
929
+ });
930
+ }
931
+ function toolResultGuardrailContext(tool, hookArgs, result, structuredResult, agent, run, turn) {
932
+ const parsedArgs = parseGuardrailContextArgs(tool, hookArgs.args);
933
+ return compact({
934
+ toolName: hookArgs.toolName,
935
+ args: parsedArgs,
936
+ rawArgs: hookArgs.args,
937
+ result,
938
+ structuredResult,
939
+ toolCallId: hookArgs.toolCallId,
940
+ internalCallId: hookArgs.internalCallId,
941
+ turn,
942
+ run: guardrailRunContext(agent, run)
943
+ });
944
+ }
945
+ function parseGuardrailContextArgs(tool, rawArgs) {
946
+ const parsedArgs = parseGuardrailArgs(rawArgs);
947
+ try {
948
+ return tool?.parseApprovalArgs?.(parsedArgs) ?? parsedArgs;
949
+ } catch {
950
+ return parsedArgs;
951
+ }
952
+ }
953
+ function parseGuardrailArgs(args) {
954
+ try {
955
+ return parseToolArgs(args);
956
+ } catch {
957
+ return args;
958
+ }
959
+ }
960
+ function guardrailRunContext(agent, run) {
961
+ return compact({
962
+ agentId: agent.id,
963
+ runId: run.runId,
964
+ sessionId: run.sessionId,
965
+ metadata: run.metadata
966
+ });
967
+ }
832
968
  function normalizeApprovalDecision(decision) {
833
969
  if (typeof decision === "boolean") {
834
970
  return { approved: decision };
@@ -852,6 +988,8 @@ function toolTraceMetadata(tool) {
852
988
  const mcpMetadata = typeof metadata === "object" && metadata !== null ? metadata : void 0;
853
989
  return {
854
990
  approvalRequired: tool.approval !== void 0,
991
+ inputGuardrailCount: tool.inputGuardrails?.length ?? 0,
992
+ outputGuardrailCount: tool.outputGuardrails?.length ?? 0,
855
993
  ...typeof mcpMetadata?.serverName === "string" && mcpMetadata.serverName.length > 0 ? { mcpServerName: mcpMetadata.serverName } : {}
856
994
  };
857
995
  }
@@ -1100,6 +1238,7 @@ var PromptRequest = class _PromptRequest {
1100
1238
  this.maxTurnCount = agent.defaultMaxTurns ?? 0;
1101
1239
  this.activeHook = agent.hook;
1102
1240
  this.approvalOptions = agent.approvals;
1241
+ this.guardrailPolicies = [...agent.guardrails];
1103
1242
  this.memoryRecorder = new PromptRequestMemory(agent, memoryContext, initialHistory);
1104
1243
  }
1105
1244
  agent;
@@ -1109,6 +1248,8 @@ var PromptRequest = class _PromptRequest {
1109
1248
  maxTurnCount;
1110
1249
  activeHook;
1111
1250
  approvalOptions;
1251
+ guardrailPolicies;
1252
+ guardrailDecisions = [];
1112
1253
  concurrency = 1;
1113
1254
  traceOptions;
1114
1255
  requestMiddlewares = [];
@@ -1131,6 +1272,10 @@ var PromptRequest = class _PromptRequest {
1131
1272
  this.approvalOptions = options;
1132
1273
  return this;
1133
1274
  }
1275
+ guardrails(policies) {
1276
+ this.guardrailPolicies = appendGuardrailPolicies(this.guardrailPolicies, policies);
1277
+ return this;
1278
+ }
1134
1279
  /**
1135
1280
  * @deprecated Use `withHook` instead.
1136
1281
  */
@@ -1175,14 +1320,37 @@ var PromptRequest = class _PromptRequest {
1175
1320
  async send() {
1176
1321
  this.startRun();
1177
1322
  const runId = globalThis.crypto.randomUUID();
1178
- const newMessages = [this.promptMessage];
1179
- this.chatHistory = await this.memoryRecorder.prepareRun(runId, newMessages);
1180
- const pendingTurnMessages = this.memoryRecorder.pendingTurnMessages(newMessages);
1181
1323
  let usage = Usage.empty();
1182
1324
  let currentTurns = 0;
1183
1325
  let lastPrompt = this.promptMessage;
1326
+ let newMessages = [this.promptMessage];
1184
1327
  const runObservers = await this.startRunObservers();
1185
1328
  try {
1329
+ const inputResult = await runInputGuardrails(this.guardrailPolicies, {
1330
+ prompt: this.promptMessage,
1331
+ history: this.chatHistory,
1332
+ inputText: textFromMessage(this.promptMessage),
1333
+ run: this.guardrailRunContext(runId)
1334
+ });
1335
+ for (const decision of inputResult.decisions) {
1336
+ await this.recordGuardrailDecision(decision, runObservers);
1337
+ }
1338
+ this.promptMessage = inputResult.prompt;
1339
+ if (inputResult.blocked) {
1340
+ const output = inputResult.message ?? "The request was blocked by a guardrail.";
1341
+ const result = {
1342
+ output,
1343
+ usage: Usage.empty(),
1344
+ messages: [this.promptMessage, Message.assistant(output)],
1345
+ guardrails: [...this.guardrailDecisions]
1346
+ };
1347
+ await runObservers.end(result);
1348
+ this.runState = "completed";
1349
+ return result;
1350
+ }
1351
+ newMessages = [this.promptMessage];
1352
+ this.chatHistory = await this.memoryRecorder.prepareRun(runId, newMessages);
1353
+ const pendingTurnMessages = this.memoryRecorder.pendingTurnMessages(newMessages);
1186
1354
  await this.runRunStartHook(newMessages);
1187
1355
  while (currentTurns <= this.maxTurnCount + 1) {
1188
1356
  const prompt = newMessages.at(-1);
@@ -1213,27 +1381,46 @@ var PromptRequest = class _PromptRequest {
1213
1381
  usage = Usage.add(usage, response.usage);
1214
1382
  await this.runCompletionResponseHook(prompt, response, newMessages);
1215
1383
  await this.runTurnEndHook(currentTurns, response, newMessages);
1216
- const assistantMessage = Message.assistant(response.choice, response.messageId);
1217
- newMessages.push(assistantMessage);
1218
- await this.memoryRecorder.commitMessages(
1219
- runId,
1220
- currentTurns,
1221
- [assistantMessage],
1222
- pendingTurnMessages
1223
- );
1224
1384
  const toolCalls = response.choice.filter(
1225
1385
  (item) => item.type === "tool_call"
1226
1386
  );
1387
+ const assistantMessage = Message.assistant(response.choice, response.messageId);
1388
+ newMessages.push(assistantMessage);
1227
1389
  if (toolCalls.length === 0) {
1390
+ if (this.steeringMessages.length > 0) {
1391
+ await this.memoryRecorder.commitMessages(
1392
+ runId,
1393
+ currentTurns,
1394
+ [assistantMessage],
1395
+ pendingTurnMessages
1396
+ );
1397
+ }
1228
1398
  if (await this.drainSteeringMessages(runId, currentTurns, newMessages, pendingTurnMessages)) {
1229
1399
  await this.memoryRecorder.commitCompletedTurn(runId, currentTurns, pendingTurnMessages);
1230
1400
  continue;
1231
1401
  }
1402
+ const guardedOutput = await this.runOutputGuardrailsForResponse(
1403
+ runId,
1404
+ usage,
1405
+ response,
1406
+ newMessages,
1407
+ runObservers
1408
+ );
1409
+ response = guardedOutput.response;
1410
+ const finalAssistantMessage = Message.assistant(response.choice, response.messageId);
1411
+ newMessages[newMessages.length - 1] = finalAssistantMessage;
1412
+ await this.memoryRecorder.commitMessages(
1413
+ runId,
1414
+ currentTurns,
1415
+ [finalAssistantMessage],
1416
+ pendingTurnMessages
1417
+ );
1232
1418
  const result = {
1233
- output: textFromAssistantContent(response.choice),
1419
+ output: guardedOutput.output,
1234
1420
  usage,
1235
1421
  messages: [...newMessages],
1236
- trace: runObservers.trace
1422
+ trace: runObservers.trace,
1423
+ guardrails: [...this.guardrailDecisions]
1237
1424
  };
1238
1425
  await this.runRunEndHook(result, newMessages);
1239
1426
  await runObservers.end(result);
@@ -1246,6 +1433,12 @@ var PromptRequest = class _PromptRequest {
1246
1433
  this.runState = "completed";
1247
1434
  return result;
1248
1435
  }
1436
+ await this.memoryRecorder.commitMessages(
1437
+ runId,
1438
+ currentTurns,
1439
+ [assistantMessage],
1440
+ pendingTurnMessages
1441
+ );
1249
1442
  const toolResults = await this.executeToolCalls(
1250
1443
  runId,
1251
1444
  toolCalls,
@@ -1256,6 +1449,9 @@ var PromptRequest = class _PromptRequest {
1256
1449
  turn: currentTurns,
1257
1450
  runObservers,
1258
1451
  toolDefinitions: request.tools
1452
+ },
1453
+ async (decision) => {
1454
+ await this.recordGuardrailDecision(decision, runObservers);
1259
1455
  }
1260
1456
  );
1261
1457
  const toolMessage = Message.tool(toolResults);
@@ -1284,18 +1480,51 @@ var PromptRequest = class _PromptRequest {
1284
1480
  }
1285
1481
  this.startRun();
1286
1482
  const runId = globalThis.crypto.randomUUID();
1287
- const newMessages = [this.promptMessage];
1288
- this.chatHistory = await this.memoryRecorder.prepareRun(runId, newMessages);
1289
- const pendingTurnMessages = this.memoryRecorder.pendingTurnMessages(newMessages);
1290
- let usage = Usage.empty();
1291
- let currentTurns = 0;
1292
- let lastPrompt = this.promptMessage;
1293
- const runObservers = await this.startRunObservers();
1294
1483
  const emit = async (event) => {
1295
1484
  await this.recordAgentEvent(runId, event);
1296
1485
  return event;
1297
1486
  };
1487
+ let usage = Usage.empty();
1488
+ let currentTurns = 0;
1489
+ let lastPrompt = this.promptMessage;
1490
+ let newMessages = [this.promptMessage];
1491
+ const runObservers = await this.startRunObservers();
1492
+ const bufferOutputDeltas = hasEnforcedOutputGuardrails(this.guardrailPolicies);
1298
1493
  try {
1494
+ const inputResult = await runInputGuardrails(this.guardrailPolicies, {
1495
+ prompt: this.promptMessage,
1496
+ history: this.chatHistory,
1497
+ inputText: textFromMessage(this.promptMessage),
1498
+ run: this.guardrailRunContext(runId)
1499
+ });
1500
+ for (const decision of inputResult.decisions) {
1501
+ await this.recordGuardrailDecision(decision, runObservers);
1502
+ yield await emit({ type: "guardrail_decision", decision });
1503
+ }
1504
+ this.promptMessage = inputResult.prompt;
1505
+ if (inputResult.blocked) {
1506
+ const output = inputResult.message ?? "The request was blocked by a guardrail.";
1507
+ const result = {
1508
+ output,
1509
+ usage: Usage.empty(),
1510
+ messages: [this.promptMessage, Message.assistant(output)],
1511
+ guardrails: [...this.guardrailDecisions]
1512
+ };
1513
+ await runObservers.end(result);
1514
+ this.runState = "completed";
1515
+ yield await emit({
1516
+ type: "final",
1517
+ runId,
1518
+ output: result.output,
1519
+ usage: result.usage,
1520
+ messages: result.messages,
1521
+ guardrails: result.guardrails
1522
+ });
1523
+ return;
1524
+ }
1525
+ newMessages = [this.promptMessage];
1526
+ this.chatHistory = await this.memoryRecorder.prepareRun(runId, newMessages);
1527
+ const pendingTurnMessages = this.memoryRecorder.pendingTurnMessages(newMessages);
1299
1528
  await this.runRunStartHook(newMessages);
1300
1529
  while (currentTurns <= this.maxTurnCount + 1) {
1301
1530
  const prompt = newMessages.at(-1);
@@ -1354,7 +1583,8 @@ var PromptRequest = class _PromptRequest {
1354
1583
  if (mapped.type === "tool_call") {
1355
1584
  emittedToolCallIds.add(mapped.toolCall.id);
1356
1585
  }
1357
- if (!bufferResponseEvents) {
1586
+ const shouldBuffer = bufferResponseEvents || bufferOutputDeltas && (mapped.type === "text_delta" || mapped.type === "reasoning_delta");
1587
+ if (!shouldBuffer) {
1358
1588
  yield await emit(addTurn(currentTurns, mapped));
1359
1589
  }
1360
1590
  }
@@ -1376,39 +1606,67 @@ var PromptRequest = class _PromptRequest {
1376
1606
  usage = Usage.add(usage, response.usage);
1377
1607
  await this.runCompletionResponseHook(prompt, response, newMessages);
1378
1608
  await this.runTurnEndHook(currentTurns, response, newMessages);
1379
- const assistantMessage = Message.assistant(response.choice, response.messageId);
1380
- newMessages.push(assistantMessage);
1381
- await this.memoryRecorder.commitMessages(
1382
- runId,
1383
- currentTurns,
1384
- [assistantMessage],
1385
- pendingTurnMessages
1386
- );
1387
1609
  const toolCalls = response.choice.filter(
1388
1610
  (item) => item.type === "tool_call"
1389
1611
  );
1390
- if (bufferResponseEvents) {
1391
- for (const event of responseStreamEvents(currentTurns, response)) {
1392
- yield await emit(event);
1393
- }
1394
- } else {
1395
- for (const toolCall of toolCalls) {
1396
- if (!emittedToolCallIds.has(toolCall.id)) {
1397
- yield await emit({ type: "tool_call", turn: currentTurns, toolCall });
1612
+ let assistantMessage = Message.assistant(response.choice, response.messageId);
1613
+ newMessages.push(assistantMessage);
1614
+ if (toolCalls.length === 0) {
1615
+ let emittedTurnEnd = false;
1616
+ if (!bufferOutputDeltas) {
1617
+ if (bufferResponseEvents) {
1618
+ for (const event of responseStreamEvents(currentTurns, response)) {
1619
+ yield await emit(event);
1620
+ }
1398
1621
  }
1622
+ yield await emit({ type: "turn_end", turn: currentTurns, response });
1623
+ emittedTurnEnd = true;
1624
+ }
1625
+ if (this.steeringMessages.length > 0) {
1626
+ await this.memoryRecorder.commitMessages(
1627
+ runId,
1628
+ currentTurns,
1629
+ [assistantMessage],
1630
+ pendingTurnMessages
1631
+ );
1399
1632
  }
1400
- }
1401
- yield await emit({ type: "turn_end", turn: currentTurns, response });
1402
- if (toolCalls.length === 0) {
1403
1633
  if (await this.drainSteeringMessages(runId, currentTurns, newMessages, pendingTurnMessages)) {
1404
1634
  await this.memoryRecorder.commitCompletedTurn(runId, currentTurns, pendingTurnMessages);
1405
1635
  continue;
1406
1636
  }
1637
+ const guardedOutput = await this.runOutputGuardrailsForResponse(
1638
+ runId,
1639
+ usage,
1640
+ response,
1641
+ newMessages,
1642
+ runObservers
1643
+ );
1644
+ for (const decision of guardedOutput.decisions) {
1645
+ yield await emit({ type: "guardrail_decision", decision });
1646
+ }
1647
+ response = guardedOutput.response;
1648
+ assistantMessage = Message.assistant(response.choice, response.messageId);
1649
+ newMessages[newMessages.length - 1] = assistantMessage;
1650
+ await this.memoryRecorder.commitMessages(
1651
+ runId,
1652
+ currentTurns,
1653
+ [assistantMessage],
1654
+ pendingTurnMessages
1655
+ );
1656
+ if (!emittedTurnEnd && (bufferResponseEvents || bufferOutputDeltas)) {
1657
+ for (const event of responseStreamEvents(currentTurns, response)) {
1658
+ yield await emit(event);
1659
+ }
1660
+ }
1661
+ if (!emittedTurnEnd) {
1662
+ yield await emit({ type: "turn_end", turn: currentTurns, response });
1663
+ }
1407
1664
  const result = {
1408
- output: textFromAssistantContent(response.choice),
1665
+ output: guardedOutput.output,
1409
1666
  usage,
1410
1667
  messages: [...newMessages],
1411
- trace: runObservers.trace
1668
+ trace: runObservers.trace,
1669
+ guardrails: [...this.guardrailDecisions]
1412
1670
  };
1413
1671
  await this.runRunEndHook(result, newMessages);
1414
1672
  await runObservers.end(result);
@@ -1425,10 +1683,29 @@ var PromptRequest = class _PromptRequest {
1425
1683
  output: result.output,
1426
1684
  usage: result.usage,
1427
1685
  messages: result.messages,
1428
- trace: result.trace
1686
+ trace: result.trace,
1687
+ guardrails: result.guardrails
1429
1688
  });
1430
1689
  return;
1431
1690
  }
1691
+ if (bufferResponseEvents) {
1692
+ for (const event of responseStreamEvents(currentTurns, response)) {
1693
+ yield await emit(event);
1694
+ }
1695
+ } else {
1696
+ for (const toolCall of toolCalls) {
1697
+ if (!emittedToolCallIds.has(toolCall.id)) {
1698
+ yield await emit({ type: "tool_call", turn: currentTurns, toolCall });
1699
+ }
1700
+ }
1701
+ }
1702
+ await this.memoryRecorder.commitMessages(
1703
+ runId,
1704
+ currentTurns,
1705
+ [assistantMessage],
1706
+ pendingTurnMessages
1707
+ );
1708
+ yield await emit({ type: "turn_end", turn: currentTurns, response });
1432
1709
  const toolResultEvents = createAsyncQueue();
1433
1710
  const toolResultsPromise = this.executeToolCalls(
1434
1711
  runId,
@@ -1444,6 +1721,10 @@ var PromptRequest = class _PromptRequest {
1444
1721
  turn: currentTurns,
1445
1722
  runObservers,
1446
1723
  toolDefinitions: request.tools
1724
+ },
1725
+ async (decision) => {
1726
+ await this.recordGuardrailDecision(decision, runObservers);
1727
+ toolResultEvents.enqueue({ type: "guardrail_decision", decision });
1447
1728
  }
1448
1729
  );
1449
1730
  toolResultsPromise.then(
@@ -1511,11 +1792,12 @@ var PromptRequest = class _PromptRequest {
1511
1792
  };
1512
1793
  }
1513
1794
  }
1514
- async executeToolCalls(runId, toolCalls, newMessages, onResult, onStreamEvent, observation) {
1795
+ async executeToolCalls(runId, toolCalls, newMessages, onResult, onStreamEvent, observation, onGuardrailDecision) {
1515
1796
  const executor = new ToolCallExecutor(
1516
1797
  this.agent,
1517
1798
  this.activeHook,
1518
1799
  this.approvalOptions,
1800
+ this.guardrailPolicies,
1519
1801
  {
1520
1802
  runId,
1521
1803
  sessionId: this.memoryContext?.sessionId,
@@ -1523,10 +1805,51 @@ var PromptRequest = class _PromptRequest {
1523
1805
  },
1524
1806
  this.concurrency,
1525
1807
  this.requestMiddlewares,
1526
- (reason) => this.cancelled(newMessages, reason)
1808
+ (reason) => this.cancelled(newMessages, reason),
1809
+ onGuardrailDecision
1527
1810
  );
1528
1811
  return executor.execute(toolCalls, onResult, onStreamEvent, observation);
1529
1812
  }
1813
+ async runOutputGuardrailsForResponse(runId, usage, response, messages, runObservers) {
1814
+ const originalOutput = textFromAssistantContent(response.choice);
1815
+ const result = await runOutputGuardrails(this.guardrailPolicies, {
1816
+ outputText: originalOutput,
1817
+ messages: [...this.chatHistory, ...messages],
1818
+ usage,
1819
+ run: this.guardrailRunContext(runId)
1820
+ });
1821
+ for (const decision of result.decisions) {
1822
+ await this.recordGuardrailDecision(decision, runObservers);
1823
+ }
1824
+ const output = result.blocked ? result.message ?? "The response was blocked by a guardrail." : result.outputText;
1825
+ if (output === originalOutput) {
1826
+ return { output, response, decisions: result.decisions };
1827
+ }
1828
+ return {
1829
+ output,
1830
+ response: {
1831
+ ...response,
1832
+ choice: [AssistantContent.text(output)]
1833
+ },
1834
+ decisions: result.decisions
1835
+ };
1836
+ }
1837
+ async recordGuardrailDecision(decision, runObservers) {
1838
+ this.guardrailDecisions.push(decision);
1839
+ await runObservers.event({
1840
+ name: "guardrail.decision",
1841
+ level: decision.action === "block" ? "WARNING" : "DEFAULT",
1842
+ attributes: guardrailDecisionAttributes(decision)
1843
+ });
1844
+ }
1845
+ guardrailRunContext(runId) {
1846
+ return compact({
1847
+ agentId: this.agent.id,
1848
+ runId,
1849
+ sessionId: this.memoryContext?.sessionId,
1850
+ metadata: this.memoryContext?.metadata
1851
+ });
1852
+ }
1530
1853
  async startRunObservers() {
1531
1854
  const failOnObserverError = this.traceOptions?.failOnObserverError === true || this.agent.observers.some((registration) => registration.failOnObserverError === true);
1532
1855
  return startAgentRunObservers(
@@ -1776,6 +2099,33 @@ function responseStreamEvents(turn, response) {
1776
2099
  }
1777
2100
  return events;
1778
2101
  }
2102
+ function textFromMessage(message) {
2103
+ if (message.role === "system") {
2104
+ return message.content;
2105
+ }
2106
+ return message.content.flatMap((content) => {
2107
+ if (content.type === "text") {
2108
+ return [content.text];
2109
+ }
2110
+ if (content.type === "document" && content.source.type === "text") {
2111
+ return [content.source.text];
2112
+ }
2113
+ return [];
2114
+ }).join("\n");
2115
+ }
2116
+ function guardrailDecisionAttributes(decision) {
2117
+ return compact({
2118
+ policyId: decision.policyId,
2119
+ guardrailId: decision.guardrailId,
2120
+ boundary: decision.boundary,
2121
+ mode: decision.mode,
2122
+ action: decision.action,
2123
+ applied: decision.applied,
2124
+ reason: decision.reason,
2125
+ message: decision.message,
2126
+ latencyMs: decision.latencyMs
2127
+ });
2128
+ }
1779
2129
 
1780
2130
  export {
1781
2131
  MaxTurnsError,
@@ -1784,4 +2134,4 @@ export {
1784
2134
  extractRagText,
1785
2135
  PromptRequest
1786
2136
  };
1787
- //# sourceMappingURL=chunk-7CQAERL3.js.map
2137
+ //# sourceMappingURL=chunk-KTTIPWE7.js.map