@absolutejs/voice 0.0.22-beta.669 → 0.0.22-beta.670

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.
@@ -40,6 +40,16 @@ export type VoiceAgentToolPolicyDecision = {
40
40
  allowed: boolean;
41
41
  reason?: string;
42
42
  };
43
+ export type VoiceAgentToolPolicy<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown> = (input: {
44
+ api: VoiceSessionHandle<TContext, TSession, TResult>;
45
+ assistantText?: string;
46
+ context: TContext;
47
+ messages: ReadonlyArray<VoiceAgentMessage>;
48
+ round: number;
49
+ session: TSession;
50
+ toolCall: VoiceAgentToolCall;
51
+ turn: VoiceTurnRecord;
52
+ }) => Promise<VoiceAgentToolPolicyDecision> | VoiceAgentToolPolicyDecision;
43
53
  export type VoiceAgentTool<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TArgs = Record<string, unknown>, TToolResult = unknown, TRouteResult = unknown> = {
44
54
  description?: string;
45
55
  execute: (input: {
@@ -187,6 +197,9 @@ export type VoiceAgentOptions<TContext = unknown, TSession extends VoiceSessionR
187
197
  turn: VoiceTurnRecord;
188
198
  }) => Promise<string | undefined> | string | undefined);
189
199
  trace?: VoiceTraceEventStore;
200
+ /** Authorize every model-requested tool before dispatch, including built-in
201
+ * lifecycle tools such as `complete` and `transfer_call`. */
202
+ toolPolicy?: VoiceAgentToolPolicy<TContext, TSession, TResult>;
190
203
  toolRuntime?: VoiceToolRuntime<TContext, TSession, TResult>;
191
204
  tools?: Array<VoiceAgentTool<TContext, TSession, Record<string, unknown>, unknown, TResult>>;
192
205
  };
@@ -68,6 +68,7 @@ export type VoiceAssistantAgentSource<TContext, TSession extends VoiceSessionRec
68
68
  model?: never;
69
69
  selectAgent?: never;
70
70
  system?: never;
71
+ toolPolicy?: never;
71
72
  tools?: never;
72
73
  } | {
73
74
  agent?: never;
@@ -78,6 +79,7 @@ export type VoiceAssistantAgentSource<TContext, TSession extends VoiceSessionRec
78
79
  model?: never;
79
80
  selectAgent?: VoiceAgentSquadOptions<TContext, TSession, TResult>["selectAgent"];
80
81
  system?: never;
82
+ toolPolicy?: never;
81
83
  tools?: never;
82
84
  } | {
83
85
  agent?: never;
@@ -88,6 +90,7 @@ export type VoiceAssistantAgentSource<TContext, TSession extends VoiceSessionRec
88
90
  model: VoiceAgentModel<TContext, TSession, TResult>;
89
91
  selectAgent?: never;
90
92
  system?: VoiceAgentOptions<TContext, TSession, TResult>["system"];
93
+ toolPolicy?: VoiceAgentOptions<TContext, TSession, TResult>["toolPolicy"];
91
94
  tools?: Array<VoiceAgentTool<TContext, TSession, Record<string, unknown>, unknown, TResult>>;
92
95
  };
93
96
  export type VoiceAssistantOptions<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown> = VoiceAssistantAgentSource<TContext, TSession, TResult> & {
package/dist/index.d.ts CHANGED
@@ -257,7 +257,7 @@ export type { StoredVoiceIncidentBundleArtifact, VoiceIncidentBundle, VoiceIncid
257
257
  export type { VoiceQualityLink, VoiceQualityMetric, VoiceQualityReport, VoiceQualityRoutesOptions, VoiceQualityStatus, VoiceQualityThresholds, } from "./core/qualityRoutes";
258
258
  export type { VoiceResilienceIOSimulator, VoiceResilienceLink, VoiceResiliencePageData, VoiceResilienceRoutesOptions, VoiceResilienceSimulationProvider, VoiceRoutingKindSummary, VoiceRoutingDecisionSummary, VoiceRoutingDecisionSummaryOptions, VoiceRoutingEvent, VoiceRoutingEventKind, VoiceRoutingSessionSummary, VoiceRoutingSessionSummaryOptions, } from "./core/resilienceRoutes";
259
259
  export type { VoiceIOProviderRouterEvent, VoiceIOProviderRouterOptions, VoiceIOProviderRouterPolicy, VoiceIOProviderRouterPolicyConfig, VoiceSTTProviderRouterOptions, VoiceTTSProviderRouterOptions, } from "./core/providerAdapters";
260
- export type { VoiceAgent, VoiceAgentMessage, VoiceAgentMessageRole, VoiceAgentModel, VoiceAgentModelInput, VoiceAgentModelOutput, VoiceAgentOptions, VoiceAgentRunResult, VoiceAgentSquadContextPolicyResult, VoiceAgentSquadHandoffPolicyResult, VoiceAgentSquadHandoffStatus, VoiceAgentSquadOptions, VoiceAgentSquadState, VoiceAgentSquadStateHandoff, VoiceAgentTool, VoiceAgentToolCall, VoiceAgentToolPolicyDecision, VoiceAgentToolResult, } from "./core/agent";
260
+ export type { VoiceAgent, VoiceAgentMessage, VoiceAgentMessageRole, VoiceAgentModel, VoiceAgentModelInput, VoiceAgentModelOutput, VoiceAgentOptions, VoiceAgentRunResult, VoiceAgentSquadContextPolicyResult, VoiceAgentSquadHandoffPolicyResult, VoiceAgentSquadHandoffStatus, VoiceAgentSquadOptions, VoiceAgentSquadState, VoiceAgentSquadStateHandoff, VoiceAgentTool, VoiceAgentToolCall, VoiceAgentToolPolicy, VoiceAgentToolPolicyDecision, VoiceAgentToolResult, } from "./core/agent";
261
261
  export type { VoiceAgentSquadContractAssertionInput, VoiceAgentSquadContractAssertionReport, VoiceAgentSquadContractDefinition, VoiceAgentSquadContractIssue, VoiceAgentSquadContractOutcome, VoiceAgentSquadContractReport, VoiceAgentSquadContractRunOptions, VoiceAgentSquadContractTurn, VoiceAgentSquadContractTurnReport, VoiceAgentSquadHandoffExpectation, VoiceAgentSquadTurnExpectation, } from "./core/agentSquadContract";
262
262
  export type { VoiceToolRetryDelay, VoiceToolRuntime, VoiceToolRuntimeExecuteInput, VoiceToolRuntimeOptions, VoiceToolRuntimeResult, } from "./core/toolRuntime";
263
263
  export type { VoiceToolContractAssertionInput, VoiceToolContractAssertionReport, VoiceToolContractCase, VoiceToolContractCaseReport, VoiceToolContractDefinition, VoiceToolContractExpectation, VoiceToolContractHandlerOptions, VoiceToolContractHTMLHandlerOptions, VoiceToolContractIssue, VoiceToolContractReport, VoiceToolContractRoutesOptions, VoiceToolContractSuiteReport, } from "./core/toolContract";
package/dist/index.js CHANGED
@@ -8412,6 +8412,47 @@ var createVoiceAgent = (options) => {
8412
8412
 
8413
8413
  `) || undefined;
8414
8414
  stamp("agent.system-resolved", { systemChars: system?.length ?? 0 });
8415
+ const recordPolicyBlock = async (toolCall, reason) => {
8416
+ const blockedResult = {
8417
+ error: reason,
8418
+ status: "error",
8419
+ toolCallId: toolCall.id,
8420
+ toolName: toolCall.name
8421
+ };
8422
+ toolResults.push(blockedResult);
8423
+ await appendVoiceAgentTrace({
8424
+ agentId: options.id,
8425
+ event: {
8426
+ error: reason,
8427
+ policyBlocked: true,
8428
+ status: "error",
8429
+ toolCallId: toolCall.id,
8430
+ toolName: toolCall.name
8431
+ },
8432
+ session: input.session,
8433
+ trace: options.trace,
8434
+ turn: input.turn,
8435
+ type: "agent.tool"
8436
+ });
8437
+ await audit?.toolCall({
8438
+ actor: {
8439
+ id: options.id,
8440
+ kind: "agent"
8441
+ },
8442
+ error: reason,
8443
+ metadata: { policyBlocked: true },
8444
+ outcome: "error",
8445
+ sessionId: input.session.id,
8446
+ toolCallId: toolCall.id,
8447
+ toolName: toolCall.name
8448
+ });
8449
+ messages.push({
8450
+ content: reason,
8451
+ name: toolCall.name,
8452
+ role: "tool",
8453
+ toolCallId: toolCall.id
8454
+ });
8455
+ };
8415
8456
  let output = {};
8416
8457
  let turnUsage;
8417
8458
  for (let round = 0;round <= maxToolRounds; round += 1) {
@@ -8482,6 +8523,27 @@ var createVoiceAgent = (options) => {
8482
8523
  turn: input.turn,
8483
8524
  type: "agent.model"
8484
8525
  });
8526
+ if (options.toolPolicy && output.toolCalls?.length) {
8527
+ const allowedToolCalls = [];
8528
+ for (const toolCall of output.toolCalls) {
8529
+ const decision = await options.toolPolicy({
8530
+ api: input.api,
8531
+ assistantText: output.assistantText,
8532
+ context: input.context,
8533
+ messages,
8534
+ round,
8535
+ session: input.session,
8536
+ toolCall,
8537
+ turn: input.turn
8538
+ });
8539
+ if (decision.allowed) {
8540
+ allowedToolCalls.push(toolCall);
8541
+ } else {
8542
+ await recordPolicyBlock(toolCall, decision.reason ?? `Voice agent tool policy blocked ${toolCall.name}.`);
8543
+ }
8544
+ }
8545
+ output.toolCalls = allowedToolCalls;
8546
+ }
8485
8547
  if (output.assistantText?.trim()) {
8486
8548
  messages.push({
8487
8549
  content: output.assistantText,
@@ -8559,45 +8621,7 @@ var createVoiceAgent = (options) => {
8559
8621
  });
8560
8622
  if (policyDecision && !policyDecision.allowed) {
8561
8623
  const error = policyDecision.reason ?? `Voice agent tool policy blocked ${tool.name}.`;
8562
- const blockedResult = {
8563
- error,
8564
- status: "error",
8565
- toolCallId: toolCall.id,
8566
- toolName: tool.name
8567
- };
8568
- toolResults.push(blockedResult);
8569
- await appendVoiceAgentTrace({
8570
- agentId: options.id,
8571
- event: {
8572
- error,
8573
- policyBlocked: true,
8574
- status: "error",
8575
- toolCallId: toolCall.id,
8576
- toolName: tool.name
8577
- },
8578
- session: input.session,
8579
- trace: options.trace,
8580
- turn: input.turn,
8581
- type: "agent.tool"
8582
- });
8583
- await audit?.toolCall({
8584
- actor: {
8585
- id: options.id,
8586
- kind: "agent"
8587
- },
8588
- error,
8589
- metadata: { policyBlocked: true },
8590
- outcome: "error",
8591
- sessionId: input.session.id,
8592
- toolCallId: toolCall.id,
8593
- toolName: tool.name
8594
- });
8595
- messages.push({
8596
- content: error,
8597
- name: tool.name,
8598
- role: "tool",
8599
- toolCallId: toolCall.id
8600
- });
8624
+ await recordPolicyBlock(toolCall, error);
8601
8625
  if (tool.endsTurn) {
8602
8626
  endTurnAfterDispatch = true;
8603
8627
  }
@@ -9498,6 +9522,7 @@ var createVoiceAssistant = (options) => {
9498
9522
  maxToolRounds: options.maxToolRounds,
9499
9523
  model: options.model,
9500
9524
  system: options.system,
9525
+ toolPolicy: options.toolPolicy,
9501
9526
  tools: options.tools
9502
9527
  } : undefined;
9503
9528
  if ("agent" in options && options.agent) {
@@ -9517,6 +9542,7 @@ var createVoiceAssistant = (options) => {
9517
9542
  maxToolRounds: options.maxToolRounds,
9518
9543
  model: options.model,
9519
9544
  system: options.system,
9545
+ toolPolicy: options.toolPolicy,
9520
9546
  tools: options.tools,
9521
9547
  trace: options.trace
9522
9548
  });
@@ -9590,6 +9616,7 @@ var createVoiceAssistant = (options) => {
9590
9616
  maxToolRounds: variant.maxToolRounds ?? baseModelOptions.maxToolRounds,
9591
9617
  model: variant.model ?? baseModelOptions.model,
9592
9618
  system: variant.system ?? baseModelOptions.system,
9619
+ toolPolicy: baseModelOptions.toolPolicy,
9593
9620
  tools: variant.tools ?? baseModelOptions.tools,
9594
9621
  trace: options.trace
9595
9622
  }) : agent;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.669",
3
+ "version": "0.0.22-beta.670",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",