@absolutejs/voice 0.0.22-beta.181 → 0.0.22-beta.182
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.
- package/dist/agent.d.ts +22 -0
- package/dist/agentSquadContract.d.ts +7 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +163 -44
- package/package.json +1 -1
package/dist/agent.d.ts
CHANGED
|
@@ -61,10 +61,30 @@ export type VoiceAgentModelOutput<TResult = unknown> = VoiceRouteResult<TResult>
|
|
|
61
61
|
export type VoiceAgentModel<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown> = {
|
|
62
62
|
generate: (input: VoiceAgentModelInput<TContext, TSession>) => Promise<VoiceAgentModelOutput<TResult>> | VoiceAgentModelOutput<TResult>;
|
|
63
63
|
};
|
|
64
|
+
export type VoiceAgentSquadHandoffStatus = 'allowed' | 'blocked' | 'max-exceeded' | 'unknown-target';
|
|
65
|
+
export type VoiceAgentSquadStateHandoff = {
|
|
66
|
+
at: number;
|
|
67
|
+
fromAgentId: string;
|
|
68
|
+
metadata?: Record<string, unknown>;
|
|
69
|
+
originalTargetAgentId?: string;
|
|
70
|
+
reason?: string;
|
|
71
|
+
status: VoiceAgentSquadHandoffStatus;
|
|
72
|
+
summary?: string;
|
|
73
|
+
targetAgentId: string;
|
|
74
|
+
turnId: string;
|
|
75
|
+
};
|
|
76
|
+
export type VoiceAgentSquadState = {
|
|
77
|
+
agentId: string;
|
|
78
|
+
handoffCount: number;
|
|
79
|
+
handoffs: VoiceAgentSquadStateHandoff[];
|
|
80
|
+
lastHandoff?: VoiceAgentSquadStateHandoff;
|
|
81
|
+
previousAgentId?: string;
|
|
82
|
+
};
|
|
64
83
|
export type VoiceAgentRunResult<TResult = unknown> = VoiceRouteResult<TResult> & {
|
|
65
84
|
agentId: string;
|
|
66
85
|
handoff?: VoiceAgentModelOutput<TResult>['handoff'];
|
|
67
86
|
messages: VoiceAgentMessage[];
|
|
87
|
+
squad?: VoiceAgentSquadState;
|
|
68
88
|
toolResults: VoiceAgentToolResult[];
|
|
69
89
|
};
|
|
70
90
|
export type VoiceAgentSquadHandoffPolicyResult<TResult = unknown> = {
|
|
@@ -120,8 +140,10 @@ export type VoiceAgentSquadOptions<TContext = unknown, TSession extends VoiceSes
|
|
|
120
140
|
onHandoff?: (input: {
|
|
121
141
|
context: TContext;
|
|
122
142
|
fromAgentId: string;
|
|
143
|
+
metadata?: Record<string, unknown>;
|
|
123
144
|
reason?: string;
|
|
124
145
|
session: TSession;
|
|
146
|
+
summary?: string;
|
|
125
147
|
targetAgentId: string;
|
|
126
148
|
turn: VoiceTurnRecord;
|
|
127
149
|
}) => Promise<void> | void;
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import type { VoiceAgent, VoiceAgentRunResult } from './agent';
|
|
1
|
+
import type { VoiceAgent, VoiceAgentRunResult, VoiceAgentSquadHandoffStatus } from './agent';
|
|
2
2
|
import type { VoiceTraceEventStore } from './trace';
|
|
3
3
|
import type { VoiceRouteResult, VoiceSessionHandle, VoiceSessionRecord } from './types';
|
|
4
4
|
export type VoiceAgentSquadContractOutcome = 'assistant' | 'complete' | 'escalate' | 'no-answer' | 'transfer' | 'voicemail';
|
|
5
5
|
export type VoiceAgentSquadHandoffExpectation = {
|
|
6
6
|
fromAgentId?: string;
|
|
7
|
-
|
|
7
|
+
metadata?: Record<string, unknown>;
|
|
8
|
+
reason?: string;
|
|
9
|
+
reasonIncludes?: string[];
|
|
10
|
+
status?: VoiceAgentSquadHandoffStatus;
|
|
11
|
+
summary?: string;
|
|
12
|
+
summaryIncludes?: string[];
|
|
8
13
|
targetAgentId?: string;
|
|
9
14
|
};
|
|
10
15
|
export type VoiceAgentSquadTurnExpectation<TResult = unknown> = {
|
package/dist/index.d.ts
CHANGED
|
@@ -110,7 +110,7 @@ export type { VoiceProviderStackChoice, VoiceProviderStackCapabilities, VoicePro
|
|
|
110
110
|
export type { VoiceQualityLink, VoiceQualityMetric, VoiceQualityReport, VoiceQualityRoutesOptions, VoiceQualityStatus, VoiceQualityThresholds } from './qualityRoutes';
|
|
111
111
|
export type { VoiceResilienceIOSimulator, VoiceResilienceLink, VoiceResiliencePageData, VoiceResilienceRoutesOptions, VoiceResilienceSimulationProvider, VoiceRoutingKindSummary, VoiceRoutingDecisionSummary, VoiceRoutingDecisionSummaryOptions, VoiceRoutingEvent, VoiceRoutingEventKind, VoiceRoutingSessionSummary, VoiceRoutingSessionSummaryOptions } from './resilienceRoutes';
|
|
112
112
|
export type { VoiceIOProviderRouterEvent, VoiceIOProviderRouterOptions, VoiceIOProviderRouterPolicy, VoiceIOProviderRouterPolicyConfig, VoiceSTTProviderRouterOptions, VoiceTTSProviderRouterOptions } from './providerAdapters';
|
|
113
|
-
export type { VoiceAgent, VoiceAgentMessage, VoiceAgentMessageRole, VoiceAgentModel, VoiceAgentModelInput, VoiceAgentModelOutput, VoiceAgentOptions, VoiceAgentRunResult, VoiceAgentSquadHandoffPolicyResult, VoiceAgentSquadOptions, VoiceAgentTool, VoiceAgentToolCall, VoiceAgentToolResult } from './agent';
|
|
113
|
+
export type { VoiceAgent, VoiceAgentMessage, VoiceAgentMessageRole, VoiceAgentModel, VoiceAgentModelInput, VoiceAgentModelOutput, VoiceAgentOptions, VoiceAgentRunResult, VoiceAgentSquadHandoffPolicyResult, VoiceAgentSquadHandoffStatus, VoiceAgentSquadOptions, VoiceAgentSquadState, VoiceAgentSquadStateHandoff, VoiceAgentTool, VoiceAgentToolCall, VoiceAgentToolResult } from './agent';
|
|
114
114
|
export type { VoiceAgentSquadContractDefinition, VoiceAgentSquadContractIssue, VoiceAgentSquadContractOutcome, VoiceAgentSquadContractReport, VoiceAgentSquadContractRunOptions, VoiceAgentSquadContractTurn, VoiceAgentSquadContractTurnReport, VoiceAgentSquadHandoffExpectation, VoiceAgentSquadTurnExpectation } from './agentSquadContract';
|
|
115
115
|
export type { VoiceToolRetryDelay, VoiceToolRuntime, VoiceToolRuntimeExecuteInput, VoiceToolRuntimeOptions, VoiceToolRuntimeResult } from './toolRuntime';
|
|
116
116
|
export type { VoiceToolContractCase, VoiceToolContractCaseReport, VoiceToolContractDefinition, VoiceToolContractExpectation, VoiceToolContractHandlerOptions, VoiceToolContractHTMLHandlerOptions, VoiceToolContractIssue, VoiceToolContractReport, VoiceToolContractRoutesOptions, VoiceToolContractSuiteReport } from './toolContract';
|
package/dist/index.js
CHANGED
|
@@ -6887,6 +6887,47 @@ var resolveVoiceAgentAuditLogger = (audit) => {
|
|
|
6887
6887
|
return "append" in audit ? createVoiceAuditLogger(audit) : audit;
|
|
6888
6888
|
};
|
|
6889
6889
|
var toAuditOutcome = (status) => status === "allowed" ? "success" : status === "blocked" ? "skipped" : "error";
|
|
6890
|
+
var createVoiceAgentSquadState = (input) => {
|
|
6891
|
+
const lastHandoff = input.handoffs.at(-1);
|
|
6892
|
+
return {
|
|
6893
|
+
agentId: input.agentId,
|
|
6894
|
+
handoffCount: input.handoffs.length,
|
|
6895
|
+
handoffs: [...input.handoffs],
|
|
6896
|
+
lastHandoff,
|
|
6897
|
+
previousAgentId: lastHandoff?.status === "allowed" ? lastHandoff.fromAgentId : undefined
|
|
6898
|
+
};
|
|
6899
|
+
};
|
|
6900
|
+
var appendVoiceAgentSquadHandoff = async (input) => {
|
|
6901
|
+
const handoff = {
|
|
6902
|
+
at: Date.now(),
|
|
6903
|
+
fromAgentId: input.fromAgentId,
|
|
6904
|
+
metadata: input.metadata,
|
|
6905
|
+
originalTargetAgentId: input.originalTargetAgentId,
|
|
6906
|
+
reason: input.reason,
|
|
6907
|
+
status: input.status,
|
|
6908
|
+
summary: input.summary,
|
|
6909
|
+
targetAgentId: input.targetAgentId,
|
|
6910
|
+
turnId: input.turn.id
|
|
6911
|
+
};
|
|
6912
|
+
input.handoffs.push(handoff);
|
|
6913
|
+
await appendVoiceAgentTrace({
|
|
6914
|
+
agentId: input.agentId,
|
|
6915
|
+
event: {
|
|
6916
|
+
fromAgentId: handoff.fromAgentId,
|
|
6917
|
+
metadata: handoff.metadata,
|
|
6918
|
+
originalTargetAgentId: handoff.originalTargetAgentId,
|
|
6919
|
+
reason: handoff.reason,
|
|
6920
|
+
status: handoff.status,
|
|
6921
|
+
summary: handoff.summary,
|
|
6922
|
+
targetAgentId: handoff.targetAgentId
|
|
6923
|
+
},
|
|
6924
|
+
session: input.session,
|
|
6925
|
+
trace: input.trace,
|
|
6926
|
+
turn: input.turn,
|
|
6927
|
+
type: "agent.handoff"
|
|
6928
|
+
});
|
|
6929
|
+
return handoff;
|
|
6930
|
+
};
|
|
6890
6931
|
var createVoiceAgentTool = (tool) => tool;
|
|
6891
6932
|
var createVoiceAgent = (options) => {
|
|
6892
6933
|
const toolMap = new Map(options.tools?.map((tool) => [tool.name, tool]) ?? []);
|
|
@@ -7187,6 +7228,7 @@ var createVoiceAgentSquad = (options) => {
|
|
|
7187
7228
|
let agent = agents.get(agentId) ?? defaultAgent;
|
|
7188
7229
|
const messages = input.messages ?? createHistoryMessages(input.session, input.turn);
|
|
7189
7230
|
const toolResults = [];
|
|
7231
|
+
const handoffs = [];
|
|
7190
7232
|
const maxHandoffs = Math.max(0, options.maxHandoffsPerTurn ?? 2);
|
|
7191
7233
|
let result = await agent.run({
|
|
7192
7234
|
...input,
|
|
@@ -7207,26 +7249,26 @@ var createVoiceAgentSquad = (options) => {
|
|
|
7207
7249
|
const targetAgentId = normalizeText3(policy?.targetAgentId) || originalTargetAgentId;
|
|
7208
7250
|
const nextAgent = agents.get(targetAgentId);
|
|
7209
7251
|
const handoffReason = policy?.summary ?? policy?.reason ?? result.handoff.reason;
|
|
7252
|
+
const handoffSummary = policy?.summary ?? result.handoff.reason ?? policy?.reason;
|
|
7210
7253
|
const handoffMetadata = {
|
|
7211
7254
|
...result.handoff.metadata,
|
|
7212
7255
|
...policy?.metadata
|
|
7213
7256
|
};
|
|
7214
7257
|
const metadata = Object.keys(handoffMetadata).length > 0 ? handoffMetadata : undefined;
|
|
7215
7258
|
if (policy?.allow === false) {
|
|
7216
|
-
await
|
|
7259
|
+
await appendVoiceAgentSquadHandoff({
|
|
7217
7260
|
agentId: options.id,
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
status: "blocked",
|
|
7224
|
-
targetAgentId
|
|
7225
|
-
},
|
|
7261
|
+
fromAgentId: agent.id,
|
|
7262
|
+
handoffs,
|
|
7263
|
+
metadata,
|
|
7264
|
+
originalTargetAgentId: originalTargetAgentId === targetAgentId ? undefined : originalTargetAgentId,
|
|
7265
|
+
reason: handoffReason,
|
|
7226
7266
|
session: input.session,
|
|
7267
|
+
status: "blocked",
|
|
7268
|
+
summary: handoffSummary,
|
|
7269
|
+
targetAgentId,
|
|
7227
7270
|
trace: options.trace,
|
|
7228
|
-
turn: input.turn
|
|
7229
|
-
type: "agent.handoff"
|
|
7271
|
+
turn: input.turn
|
|
7230
7272
|
});
|
|
7231
7273
|
await audit?.handoff({
|
|
7232
7274
|
actor: {
|
|
@@ -7247,24 +7289,27 @@ var createVoiceAgentSquad = (options) => {
|
|
|
7247
7289
|
reason: handoffReason ?? `Blocked handoff to ${targetAgentId}`
|
|
7248
7290
|
},
|
|
7249
7291
|
handoff: undefined,
|
|
7292
|
+
squad: createVoiceAgentSquadState({
|
|
7293
|
+
agentId: agent.id,
|
|
7294
|
+
handoffs
|
|
7295
|
+
}),
|
|
7250
7296
|
toolResults
|
|
7251
7297
|
};
|
|
7252
7298
|
}
|
|
7253
7299
|
if (!nextAgent) {
|
|
7254
|
-
await
|
|
7300
|
+
await appendVoiceAgentSquadHandoff({
|
|
7255
7301
|
agentId: options.id,
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
status: "unknown-target",
|
|
7262
|
-
targetAgentId
|
|
7263
|
-
},
|
|
7302
|
+
fromAgentId: agent.id,
|
|
7303
|
+
handoffs,
|
|
7304
|
+
metadata,
|
|
7305
|
+
originalTargetAgentId: originalTargetAgentId === targetAgentId ? undefined : originalTargetAgentId,
|
|
7306
|
+
reason: handoffReason,
|
|
7264
7307
|
session: input.session,
|
|
7308
|
+
status: "unknown-target",
|
|
7309
|
+
summary: handoffSummary,
|
|
7310
|
+
targetAgentId,
|
|
7265
7311
|
trace: options.trace,
|
|
7266
|
-
turn: input.turn
|
|
7267
|
-
type: "agent.handoff"
|
|
7312
|
+
turn: input.turn
|
|
7268
7313
|
});
|
|
7269
7314
|
await audit?.handoff({
|
|
7270
7315
|
actor: {
|
|
@@ -7285,31 +7330,36 @@ var createVoiceAgentSquad = (options) => {
|
|
|
7285
7330
|
reason: `Unknown handoff target: ${targetAgentId}`
|
|
7286
7331
|
},
|
|
7287
7332
|
handoff: undefined,
|
|
7333
|
+
squad: createVoiceAgentSquadState({
|
|
7334
|
+
agentId: agent.id,
|
|
7335
|
+
handoffs
|
|
7336
|
+
}),
|
|
7288
7337
|
toolResults
|
|
7289
7338
|
};
|
|
7290
7339
|
}
|
|
7291
7340
|
await options.onHandoff?.({
|
|
7292
7341
|
context: input.context,
|
|
7293
7342
|
fromAgentId: agent.id,
|
|
7343
|
+
metadata,
|
|
7294
7344
|
reason: handoffReason,
|
|
7295
7345
|
session: input.session,
|
|
7346
|
+
summary: handoffSummary,
|
|
7296
7347
|
targetAgentId: nextAgent.id,
|
|
7297
7348
|
turn: input.turn
|
|
7298
7349
|
});
|
|
7299
|
-
await
|
|
7350
|
+
await appendVoiceAgentSquadHandoff({
|
|
7300
7351
|
agentId: options.id,
|
|
7301
|
-
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
status: "allowed",
|
|
7307
|
-
targetAgentId: nextAgent.id
|
|
7308
|
-
},
|
|
7352
|
+
fromAgentId: agent.id,
|
|
7353
|
+
handoffs,
|
|
7354
|
+
metadata,
|
|
7355
|
+
originalTargetAgentId: originalTargetAgentId === nextAgent.id ? undefined : originalTargetAgentId,
|
|
7356
|
+
reason: handoffReason,
|
|
7309
7357
|
session: input.session,
|
|
7358
|
+
status: "allowed",
|
|
7359
|
+
summary: handoffSummary,
|
|
7360
|
+
targetAgentId: nextAgent.id,
|
|
7310
7361
|
trace: options.trace,
|
|
7311
|
-
turn: input.turn
|
|
7312
|
-
type: "agent.handoff"
|
|
7362
|
+
turn: input.turn
|
|
7313
7363
|
});
|
|
7314
7364
|
await audit?.handoff({
|
|
7315
7365
|
actor: {
|
|
@@ -7324,7 +7374,7 @@ var createVoiceAgentSquad = (options) => {
|
|
|
7324
7374
|
toAgentId: nextAgent.id
|
|
7325
7375
|
});
|
|
7326
7376
|
messages.push({
|
|
7327
|
-
content: handoffReason ?? `Handoff to ${nextAgent.id}`,
|
|
7377
|
+
content: handoffSummary ?? handoffReason ?? `Handoff to ${nextAgent.id}`,
|
|
7328
7378
|
metadata,
|
|
7329
7379
|
name: nextAgent.id,
|
|
7330
7380
|
role: "system"
|
|
@@ -7338,19 +7388,18 @@ var createVoiceAgentSquad = (options) => {
|
|
|
7338
7388
|
toolResults.push(...result.toolResults);
|
|
7339
7389
|
}
|
|
7340
7390
|
if (result.handoff) {
|
|
7341
|
-
await
|
|
7391
|
+
await appendVoiceAgentSquadHandoff({
|
|
7342
7392
|
agentId: options.id,
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
status: "max-exceeded",
|
|
7348
|
-
targetAgentId: result.handoff.targetAgentId
|
|
7349
|
-
},
|
|
7393
|
+
fromAgentId: agent.id,
|
|
7394
|
+
handoffs,
|
|
7395
|
+
metadata: result.handoff.metadata,
|
|
7396
|
+
reason: result.handoff.reason,
|
|
7350
7397
|
session: input.session,
|
|
7398
|
+
status: "max-exceeded",
|
|
7399
|
+
summary: result.handoff.reason,
|
|
7400
|
+
targetAgentId: result.handoff.targetAgentId,
|
|
7351
7401
|
trace: options.trace,
|
|
7352
|
-
turn: input.turn
|
|
7353
|
-
type: "agent.handoff"
|
|
7402
|
+
turn: input.turn
|
|
7354
7403
|
});
|
|
7355
7404
|
await audit?.handoff({
|
|
7356
7405
|
actor: {
|
|
@@ -7371,12 +7420,20 @@ var createVoiceAgentSquad = (options) => {
|
|
|
7371
7420
|
reason: `Max handoffs exceeded: ${maxHandoffs}`
|
|
7372
7421
|
},
|
|
7373
7422
|
handoff: undefined,
|
|
7423
|
+
squad: createVoiceAgentSquadState({
|
|
7424
|
+
agentId: agent.id,
|
|
7425
|
+
handoffs
|
|
7426
|
+
}),
|
|
7374
7427
|
toolResults
|
|
7375
7428
|
};
|
|
7376
7429
|
}
|
|
7377
7430
|
return {
|
|
7378
7431
|
...result,
|
|
7379
7432
|
agentId,
|
|
7433
|
+
squad: createVoiceAgentSquadState({
|
|
7434
|
+
agentId,
|
|
7435
|
+
handoffs
|
|
7436
|
+
}),
|
|
7380
7437
|
toolResults
|
|
7381
7438
|
};
|
|
7382
7439
|
};
|
|
@@ -14433,9 +14490,16 @@ var getPayloadString2 = (event, key) => {
|
|
|
14433
14490
|
const value = event.payload[key];
|
|
14434
14491
|
return typeof value === "string" ? value : undefined;
|
|
14435
14492
|
};
|
|
14493
|
+
var getPayloadRecord = (event, key) => {
|
|
14494
|
+
const value = event.payload[key];
|
|
14495
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
|
|
14496
|
+
};
|
|
14436
14497
|
var toHandoffExpectation = (event) => ({
|
|
14437
14498
|
fromAgentId: getPayloadString2(event, "fromAgentId"),
|
|
14499
|
+
metadata: getPayloadRecord(event, "metadata"),
|
|
14500
|
+
reason: getPayloadString2(event, "reason"),
|
|
14438
14501
|
status: getPayloadString2(event, "status"),
|
|
14502
|
+
summary: getPayloadString2(event, "summary"),
|
|
14439
14503
|
targetAgentId: getPayloadString2(event, "targetAgentId")
|
|
14440
14504
|
});
|
|
14441
14505
|
var createContractApi = (session) => ({
|
|
@@ -14465,6 +14529,28 @@ var appendIssue = (issues, issue, turnId) => {
|
|
|
14465
14529
|
turnId: issue.turnId ?? turnId
|
|
14466
14530
|
});
|
|
14467
14531
|
};
|
|
14532
|
+
var assertIncludes = (input) => {
|
|
14533
|
+
const actual = normalizeIncludes(input.actual?.join(" ") ?? "");
|
|
14534
|
+
for (const expected of input.expected ?? []) {
|
|
14535
|
+
if (!actual.includes(normalizeIncludes(expected))) {
|
|
14536
|
+
appendIssue(input.issues, {
|
|
14537
|
+
code: input.code,
|
|
14538
|
+
message: `Expected handoff ${input.handoffIndex + 1} ${input.label} to include: ${expected}`
|
|
14539
|
+
}, input.turnId);
|
|
14540
|
+
}
|
|
14541
|
+
}
|
|
14542
|
+
};
|
|
14543
|
+
var assertMetadata = (input) => {
|
|
14544
|
+
for (const [key, expectedValue] of Object.entries(input.expected ?? {})) {
|
|
14545
|
+
const actualValue = input.actual?.[key];
|
|
14546
|
+
if (actualValue !== expectedValue) {
|
|
14547
|
+
appendIssue(input.issues, {
|
|
14548
|
+
code: "agent_squad.handoff_metadata_mismatch",
|
|
14549
|
+
message: `Expected handoff ${input.handoffIndex + 1} metadata ${key} ${String(expectedValue)}, saw ${String(actualValue ?? "none")}.`
|
|
14550
|
+
}, input.turnId);
|
|
14551
|
+
}
|
|
14552
|
+
}
|
|
14553
|
+
};
|
|
14468
14554
|
var runVoiceAgentSquadContract = async (options) => {
|
|
14469
14555
|
const session = options.session ?? createVoiceSessionRecord(`agent-squad-contract-${options.contract.id}`, options.contract.scenarioId ?? options.contract.id);
|
|
14470
14556
|
const api = options.api ?? createContractApi(session);
|
|
@@ -14531,6 +14617,39 @@ var runVoiceAgentSquadContract = async (options) => {
|
|
|
14531
14617
|
}, turn.id);
|
|
14532
14618
|
}
|
|
14533
14619
|
}
|
|
14620
|
+
for (const key of ["reason", "summary"]) {
|
|
14621
|
+
if (expectedHandoff[key] && actual[key] !== expectedHandoff[key]) {
|
|
14622
|
+
appendIssue(turnIssues, {
|
|
14623
|
+
code: `agent_squad.handoff_${key}_mismatch`,
|
|
14624
|
+
message: `Expected handoff ${handoffIndex + 1} ${key} ${expectedHandoff[key]}, saw ${actual[key] ?? "none"}.`
|
|
14625
|
+
}, turn.id);
|
|
14626
|
+
}
|
|
14627
|
+
}
|
|
14628
|
+
assertIncludes({
|
|
14629
|
+
actual: actual.reason ? [actual.reason] : undefined,
|
|
14630
|
+
code: "agent_squad.handoff_reason_missing",
|
|
14631
|
+
expected: expectedHandoff.reasonIncludes,
|
|
14632
|
+
handoffIndex,
|
|
14633
|
+
issues: turnIssues,
|
|
14634
|
+
label: "reason",
|
|
14635
|
+
turnId: turn.id
|
|
14636
|
+
});
|
|
14637
|
+
assertIncludes({
|
|
14638
|
+
actual: actual.summary ? [actual.summary] : undefined,
|
|
14639
|
+
code: "agent_squad.handoff_summary_missing",
|
|
14640
|
+
expected: expectedHandoff.summaryIncludes,
|
|
14641
|
+
handoffIndex,
|
|
14642
|
+
issues: turnIssues,
|
|
14643
|
+
label: "summary",
|
|
14644
|
+
turnId: turn.id
|
|
14645
|
+
});
|
|
14646
|
+
assertMetadata({
|
|
14647
|
+
actual: actual.metadata,
|
|
14648
|
+
expected: expectedHandoff.metadata,
|
|
14649
|
+
handoffIndex,
|
|
14650
|
+
issues: turnIssues,
|
|
14651
|
+
turnId: turn.id
|
|
14652
|
+
});
|
|
14534
14653
|
}
|
|
14535
14654
|
for (const issue of expected?.result?.({
|
|
14536
14655
|
result: result.result,
|