@absolutejs/voice 0.0.22-beta.62 → 0.0.22-beta.64
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/client/opsStatusWidget.d.ts +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +234 -2
- package/dist/toolContract.d.ts +130 -0
- package/package.json +1 -1
|
@@ -29,7 +29,7 @@ export type VoiceOpsStatusWidgetOptions = VoiceAppKitStatusClientOptions & {
|
|
|
29
29
|
includeLinks?: boolean;
|
|
30
30
|
title?: string;
|
|
31
31
|
};
|
|
32
|
-
export declare const getVoiceOpsStatusLabel: (report?: VoiceAppKitStatusReport | null, error?: string | null) => "
|
|
32
|
+
export declare const getVoiceOpsStatusLabel: (report?: VoiceAppKitStatusReport | null, error?: string | null) => "Passing" | "Unavailable" | "Checking" | "Needs attention";
|
|
33
33
|
export declare const createVoiceOpsStatusViewModel: (snapshot: VoiceAppKitStatusSnapshot, options?: VoiceOpsStatusWidgetOptions) => VoiceOpsStatusViewModel;
|
|
34
34
|
export declare const renderVoiceOpsStatusHTML: (snapshot: VoiceAppKitStatusSnapshot, options?: VoiceOpsStatusWidgetOptions) => string;
|
|
35
35
|
export declare const getVoiceOpsStatusCSS: () => string;
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export { createVoiceWorkflowContract, createVoiceWorkflowContractHandler, create
|
|
|
8
8
|
export { createVoiceSessionListRoutes, createVoiceSessionReplayHTMLHandler, createVoiceSessionReplayJSONHandler, createVoiceSessionReplayRoutes, createVoiceSessionsHTMLHandler, createVoiceSessionsJSONHandler, renderVoiceSessionsHTML, summarizeVoiceSessions, summarizeVoiceSessionReplay } from './sessionReplay';
|
|
9
9
|
export { createVoiceAgent, createVoiceAgentSquad, createVoiceAgentTool } from './agent';
|
|
10
10
|
export { createVoiceToolIdempotencyKey, createVoiceToolRuntime } from './toolRuntime';
|
|
11
|
+
export { createVoiceToolContract, createVoiceToolContractHTMLHandler, createVoiceToolContractJSONHandler, createVoiceToolContractRoutes, createVoiceToolRuntimeContractDefaults, renderVoiceToolContractHTML, runVoiceToolContractSuite, runVoiceToolContract } from './toolContract';
|
|
11
12
|
export { createStoredVoiceCallReviewArtifact, createStoredVoiceExternalObjectMap, createStoredVoiceIntegrationEvent, createStoredVoiceOpsTask, createVoiceFileExternalObjectMapStore, createVoiceFileAssistantMemoryStore, createVoiceFileIntegrationEventStore, createVoiceFileReviewStore, createVoiceFileRuntimeStorage, createVoiceFileSessionStore, createVoiceFileTaskStore, createVoiceFileTraceSinkDeliveryStore, createVoiceFileTraceEventStore } from './fileStore';
|
|
12
13
|
export { createVoiceAssistantMemoryHandle, createVoiceAssistantMemoryRecord, createVoiceMemoryAssistantMemoryStore, resolveVoiceAssistantMemoryNamespace } from './assistantMemory';
|
|
13
14
|
export { createAnthropicVoiceAssistantModel, createGeminiVoiceAssistantModel, createJSONVoiceAssistantModel, createOpenAIVoiceAssistantModel, resolveVoiceProviderRoutingPolicyPreset, createVoiceProviderRouter } from './modelAdapters';
|
|
@@ -55,6 +56,7 @@ export type { VoiceResilienceIOSimulator, VoiceResilienceLink, VoiceResiliencePa
|
|
|
55
56
|
export type { VoiceIOProviderRouterEvent, VoiceIOProviderRouterOptions, VoiceIOProviderRouterPolicy, VoiceIOProviderRouterPolicyConfig, VoiceSTTProviderRouterOptions, VoiceTTSProviderRouterOptions } from './providerAdapters';
|
|
56
57
|
export type { VoiceAgent, VoiceAgentMessage, VoiceAgentMessageRole, VoiceAgentModel, VoiceAgentModelInput, VoiceAgentModelOutput, VoiceAgentOptions, VoiceAgentRunResult, VoiceAgentSquadOptions, VoiceAgentTool, VoiceAgentToolCall, VoiceAgentToolResult } from './agent';
|
|
57
58
|
export type { VoiceToolRetryDelay, VoiceToolRuntime, VoiceToolRuntimeExecuteInput, VoiceToolRuntimeOptions, VoiceToolRuntimeResult } from './toolRuntime';
|
|
59
|
+
export type { VoiceToolContractCase, VoiceToolContractCaseReport, VoiceToolContractDefinition, VoiceToolContractExpectation, VoiceToolContractHandlerOptions, VoiceToolContractHTMLHandlerOptions, VoiceToolContractIssue, VoiceToolContractReport, VoiceToolContractRoutesOptions, VoiceToolContractSuiteReport } from './toolContract';
|
|
58
60
|
export type { VoiceOpsRuntime, VoiceOpsRuntimeConfig, VoiceOpsRuntimeSummary, VoiceOpsRuntimeSinkWorkerConfig, VoiceOpsRuntimeTaskWorkerConfig, VoiceOpsRuntimeTickResult, VoiceOpsRuntimeWebhookWorkerConfig } from './opsRuntime';
|
|
59
61
|
export type { VoiceOpsPresetName, VoiceOpsPresetOverrides, VoiceResolvedOpsPreset } from './opsPresets';
|
|
60
62
|
export type { VoiceOutcomeRecipe, VoiceOutcomeRecipeName, VoiceOutcomeRecipeOptions } from './outcomeRecipes';
|
package/dist/index.js
CHANGED
|
@@ -9946,6 +9946,230 @@ var createVoiceToolIdempotencyKey = (input) => {
|
|
|
9946
9946
|
args
|
|
9947
9947
|
].join(":");
|
|
9948
9948
|
};
|
|
9949
|
+
// src/toolContract.ts
|
|
9950
|
+
import { Elysia as Elysia12 } from "elysia";
|
|
9951
|
+
var createDefaultSession = (contractId, caseId) => createVoiceSessionRecord(`tool-contract-${contractId}-${caseId}`);
|
|
9952
|
+
var createDefaultTurn = (caseId) => ({
|
|
9953
|
+
committedAt: Date.now(),
|
|
9954
|
+
id: `turn-${caseId}`,
|
|
9955
|
+
text: `Run tool contract case ${caseId}.`,
|
|
9956
|
+
transcripts: []
|
|
9957
|
+
});
|
|
9958
|
+
var defaultApi = {};
|
|
9959
|
+
var sameJSON = (left, right) => JSON.stringify(left) === JSON.stringify(right);
|
|
9960
|
+
var escapeHtml13 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
9961
|
+
var evaluateExpectation = (input) => {
|
|
9962
|
+
const issues = [];
|
|
9963
|
+
const expect = input.expect;
|
|
9964
|
+
if (!expect) {
|
|
9965
|
+
return issues;
|
|
9966
|
+
}
|
|
9967
|
+
if (expect.expectStatus && input.status !== expect.expectStatus) {
|
|
9968
|
+
issues.push({
|
|
9969
|
+
caseId: input.caseId,
|
|
9970
|
+
code: "tool.status_mismatch",
|
|
9971
|
+
message: `Expected ${expect.expectStatus}, saw ${input.status}.`
|
|
9972
|
+
});
|
|
9973
|
+
}
|
|
9974
|
+
if (typeof expect.expectedAttempts === "number" && input.attempts !== expect.expectedAttempts) {
|
|
9975
|
+
issues.push({
|
|
9976
|
+
caseId: input.caseId,
|
|
9977
|
+
code: "tool.attempt_mismatch",
|
|
9978
|
+
message: `Expected ${expect.expectedAttempts} attempts, saw ${input.attempts}.`
|
|
9979
|
+
});
|
|
9980
|
+
}
|
|
9981
|
+
if (expect.expectedResult !== undefined && !sameJSON(input.result, expect.expectedResult)) {
|
|
9982
|
+
issues.push({
|
|
9983
|
+
caseId: input.caseId,
|
|
9984
|
+
code: "tool.result_mismatch",
|
|
9985
|
+
message: "Tool result did not match expected result."
|
|
9986
|
+
});
|
|
9987
|
+
}
|
|
9988
|
+
if (expect.expectedErrorIncludes && !input.error?.includes(expect.expectedErrorIncludes)) {
|
|
9989
|
+
issues.push({
|
|
9990
|
+
caseId: input.caseId,
|
|
9991
|
+
code: "tool.error_mismatch",
|
|
9992
|
+
message: `Expected error to include ${expect.expectedErrorIncludes}.`
|
|
9993
|
+
});
|
|
9994
|
+
}
|
|
9995
|
+
if (typeof expect.expectTimedOut === "boolean" && input.timedOut !== expect.expectTimedOut) {
|
|
9996
|
+
issues.push({
|
|
9997
|
+
caseId: input.caseId,
|
|
9998
|
+
code: "tool.timeout_mismatch",
|
|
9999
|
+
message: `Expected timedOut=${String(expect.expectTimedOut)}, saw ${String(input.timedOut)}.`
|
|
10000
|
+
});
|
|
10001
|
+
}
|
|
10002
|
+
if (typeof expect.maxElapsedMs === "number" && input.elapsedMs > expect.maxElapsedMs) {
|
|
10003
|
+
issues.push({
|
|
10004
|
+
caseId: input.caseId,
|
|
10005
|
+
code: "tool.elapsed_exceeded",
|
|
10006
|
+
message: `Expected elapsed <= ${expect.maxElapsedMs}ms, saw ${input.elapsedMs}ms.`
|
|
10007
|
+
});
|
|
10008
|
+
}
|
|
10009
|
+
return issues;
|
|
10010
|
+
};
|
|
10011
|
+
var runVoiceToolContract = async (definition) => {
|
|
10012
|
+
const cases = [];
|
|
10013
|
+
for (const testCase of definition.cases) {
|
|
10014
|
+
const session = testCase.session ?? createDefaultSession(definition.id, testCase.id);
|
|
10015
|
+
const turn = testCase.turn ?? createDefaultTurn(testCase.id);
|
|
10016
|
+
const context = testCase.context ?? {};
|
|
10017
|
+
const runtimeOptions = {
|
|
10018
|
+
...definition.defaultRuntime,
|
|
10019
|
+
...testCase.runtime
|
|
10020
|
+
};
|
|
10021
|
+
const runtime = createVoiceToolRuntime(runtimeOptions);
|
|
10022
|
+
const toolCall = {
|
|
10023
|
+
args: testCase.args,
|
|
10024
|
+
id: testCase.toolCallId ?? testCase.id,
|
|
10025
|
+
name: definition.tool.name
|
|
10026
|
+
};
|
|
10027
|
+
const executeOnce = () => runtime.execute({
|
|
10028
|
+
api: defaultApi,
|
|
10029
|
+
args: toolCall.args,
|
|
10030
|
+
context,
|
|
10031
|
+
session,
|
|
10032
|
+
tool: definition.tool,
|
|
10033
|
+
toolCallId: toolCall.id,
|
|
10034
|
+
turn
|
|
10035
|
+
});
|
|
10036
|
+
const result = await executeOnce();
|
|
10037
|
+
let issues2 = evaluateExpectation({
|
|
10038
|
+
attempts: result.attempts,
|
|
10039
|
+
caseId: testCase.id,
|
|
10040
|
+
elapsedMs: result.elapsedMs,
|
|
10041
|
+
error: result.error,
|
|
10042
|
+
expect: testCase.expect,
|
|
10043
|
+
result: result.result,
|
|
10044
|
+
status: result.status,
|
|
10045
|
+
timedOut: result.timedOut
|
|
10046
|
+
});
|
|
10047
|
+
if (testCase.expect?.expectIdempotent) {
|
|
10048
|
+
const second = await executeOnce();
|
|
10049
|
+
if (second.result !== result.result && !sameJSON(second.result, result.result)) {
|
|
10050
|
+
issues2.push({
|
|
10051
|
+
caseId: testCase.id,
|
|
10052
|
+
code: "tool.idempotency_result_mismatch",
|
|
10053
|
+
message: "Repeated idempotent execution returned a different result."
|
|
10054
|
+
});
|
|
10055
|
+
}
|
|
10056
|
+
if (second.idempotencyKey !== result.idempotencyKey) {
|
|
10057
|
+
issues2.push({
|
|
10058
|
+
caseId: testCase.id,
|
|
10059
|
+
code: "tool.idempotency_key_mismatch",
|
|
10060
|
+
message: "Repeated idempotent execution used a different idempotency key."
|
|
10061
|
+
});
|
|
10062
|
+
}
|
|
10063
|
+
}
|
|
10064
|
+
cases.push({
|
|
10065
|
+
attempts: result.attempts,
|
|
10066
|
+
caseId: testCase.id,
|
|
10067
|
+
elapsedMs: result.elapsedMs,
|
|
10068
|
+
error: result.error,
|
|
10069
|
+
issues: issues2,
|
|
10070
|
+
label: testCase.label,
|
|
10071
|
+
pass: issues2.length === 0,
|
|
10072
|
+
status: result.status,
|
|
10073
|
+
timedOut: result.timedOut
|
|
10074
|
+
});
|
|
10075
|
+
}
|
|
10076
|
+
const issues = cases.flatMap((testCase) => testCase.issues);
|
|
10077
|
+
return {
|
|
10078
|
+
cases,
|
|
10079
|
+
contractId: definition.id,
|
|
10080
|
+
label: definition.label,
|
|
10081
|
+
issues,
|
|
10082
|
+
pass: issues.length === 0,
|
|
10083
|
+
toolName: definition.tool.name
|
|
10084
|
+
};
|
|
10085
|
+
};
|
|
10086
|
+
var createVoiceToolContract = (definition) => ({
|
|
10087
|
+
assert: async () => {
|
|
10088
|
+
const report = await runVoiceToolContract(definition);
|
|
10089
|
+
if (!report.pass) {
|
|
10090
|
+
throw new Error(`Voice tool contract ${definition.id} failed: ${report.issues.map((issue) => issue.message).join(" ")}`);
|
|
10091
|
+
}
|
|
10092
|
+
return report;
|
|
10093
|
+
},
|
|
10094
|
+
definition,
|
|
10095
|
+
run: () => runVoiceToolContract(definition)
|
|
10096
|
+
});
|
|
10097
|
+
var createVoiceToolRuntimeContractDefaults = () => ({
|
|
10098
|
+
idempotencyKey: ({ args, session, toolCallId, toolName, turn }) => createVoiceToolIdempotencyKey({
|
|
10099
|
+
args,
|
|
10100
|
+
sessionId: session.id,
|
|
10101
|
+
toolCallId,
|
|
10102
|
+
toolName,
|
|
10103
|
+
turnId: turn.id
|
|
10104
|
+
}),
|
|
10105
|
+
idempotencyTtlMs: 60000,
|
|
10106
|
+
maxRetries: 1,
|
|
10107
|
+
timeoutMs: 5000
|
|
10108
|
+
});
|
|
10109
|
+
var runVoiceToolContractSuite = async (options) => {
|
|
10110
|
+
const contracts = await Promise.all(options.contracts.map((contract) => runVoiceToolContract(contract)));
|
|
10111
|
+
const passed = contracts.filter((contract) => contract.pass).length;
|
|
10112
|
+
const failed = contracts.length - passed;
|
|
10113
|
+
return {
|
|
10114
|
+
checkedAt: Date.now(),
|
|
10115
|
+
contracts,
|
|
10116
|
+
failed,
|
|
10117
|
+
passed,
|
|
10118
|
+
status: failed > 0 ? "fail" : "pass",
|
|
10119
|
+
total: contracts.length
|
|
10120
|
+
};
|
|
10121
|
+
};
|
|
10122
|
+
var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
10123
|
+
const title = options.title ?? "Voice Tool Contracts";
|
|
10124
|
+
const contracts = report.contracts.map((contract) => {
|
|
10125
|
+
const cases = contract.cases.map((testCase) => `<tr>
|
|
10126
|
+
<td>${escapeHtml13(testCase.label ?? testCase.caseId)}</td>
|
|
10127
|
+
<td class="${testCase.pass ? "pass" : "fail"}">${testCase.pass ? "pass" : "fail"}</td>
|
|
10128
|
+
<td>${escapeHtml13(testCase.status)}</td>
|
|
10129
|
+
<td>${String(testCase.attempts)}</td>
|
|
10130
|
+
<td>${String(testCase.elapsedMs)}ms</td>
|
|
10131
|
+
<td>${testCase.timedOut ? "yes" : "no"}</td>
|
|
10132
|
+
<td>${escapeHtml13(testCase.issues.map((issue) => issue.message).join(" ") || testCase.error || "")}</td>
|
|
10133
|
+
</tr>`).join("");
|
|
10134
|
+
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
10135
|
+
<div class="contract-header">
|
|
10136
|
+
<div>
|
|
10137
|
+
<p class="eyebrow">${escapeHtml13(contract.toolName)}</p>
|
|
10138
|
+
<h2>${escapeHtml13(contract.label ?? contract.contractId)}</h2>
|
|
10139
|
+
</div>
|
|
10140
|
+
<strong class="${contract.pass ? "pass" : "fail"}">${contract.pass ? "Passing" : "Failing"}</strong>
|
|
10141
|
+
</div>
|
|
10142
|
+
<table>
|
|
10143
|
+
<thead><tr><th>Case</th><th>Status</th><th>Result</th><th>Attempts</th><th>Elapsed</th><th>Timed out</th><th>Issues</th></tr></thead>
|
|
10144
|
+
<tbody>${cases}</tbody>
|
|
10145
|
+
</table>
|
|
10146
|
+
</section>`;
|
|
10147
|
+
}).join("");
|
|
10148
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml13(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.contract{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.14),rgba(245,158,11,.12))}.eyebrow{color:#fbbf24;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.contract-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}h2{margin:.2rem 0 1rem}.pass{color:#86efac}.fail{color:#fca5a5}.contract.fail{border-color:rgba(248,113,113,.45)}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2a323a;padding:12px;text-align:left;vertical-align:top}th{color:#a8b0b8;font-size:.82rem}@media(max-width:800px){main{padding:18px}table{display:block;overflow:auto}.contract-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Tool Reliability</p><h1>${escapeHtml13(title)}</h1><div class="summary"><span class="pill ${report.status === "pass" ? "pass" : "fail"}">${escapeHtml13(report.status)}</span><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} contracts</span></div></section>${contracts || '<section class="contract"><p>No tool contracts configured.</p></section>'}</main></body></html>`;
|
|
10149
|
+
};
|
|
10150
|
+
var createVoiceToolContractJSONHandler = (options) => () => runVoiceToolContractSuite(options);
|
|
10151
|
+
var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
10152
|
+
const report = await runVoiceToolContractSuite(options);
|
|
10153
|
+
const render = options.render ?? ((input) => renderVoiceToolContractHTML(input, options));
|
|
10154
|
+
const body = await render(report);
|
|
10155
|
+
return new Response(body, {
|
|
10156
|
+
headers: {
|
|
10157
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
10158
|
+
...options.headers
|
|
10159
|
+
}
|
|
10160
|
+
});
|
|
10161
|
+
};
|
|
10162
|
+
var createVoiceToolContractRoutes = (options) => {
|
|
10163
|
+
const path = options.path ?? "/api/tool-contracts";
|
|
10164
|
+
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
10165
|
+
const routes = new Elysia12({
|
|
10166
|
+
name: options.name ?? "absolutejs-voice-tool-contracts"
|
|
10167
|
+
}).get(path, createVoiceToolContractJSONHandler(options));
|
|
10168
|
+
if (htmlPath) {
|
|
10169
|
+
routes.get(htmlPath, createVoiceToolContractHTMLHandler(options));
|
|
10170
|
+
}
|
|
10171
|
+
return routes;
|
|
10172
|
+
};
|
|
9949
10173
|
// src/fileStore.ts
|
|
9950
10174
|
import { mkdir as mkdir2, readFile, readdir, rename, rm, writeFile } from "fs/promises";
|
|
9951
10175
|
import { join } from "path";
|
|
@@ -12039,7 +12263,7 @@ var createVoiceMemoryStore = () => {
|
|
|
12039
12263
|
return { get, getOrCreate, list, remove, set };
|
|
12040
12264
|
};
|
|
12041
12265
|
// src/opsWebhook.ts
|
|
12042
|
-
import { Elysia as
|
|
12266
|
+
import { Elysia as Elysia13 } from "elysia";
|
|
12043
12267
|
var toHex5 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
12044
12268
|
var signVoiceOpsWebhookBody = async (input) => {
|
|
12045
12269
|
const encoder = new TextEncoder;
|
|
@@ -12169,7 +12393,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
|
|
|
12169
12393
|
};
|
|
12170
12394
|
var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
|
|
12171
12395
|
const path = options.path ?? "/api/voice-ops/webhook";
|
|
12172
|
-
return new
|
|
12396
|
+
return new Elysia13().post(path, async ({ body, request, set }) => {
|
|
12173
12397
|
const bodyText = typeof body === "string" ? body : JSON.stringify(body);
|
|
12174
12398
|
if (options.signingSecret) {
|
|
12175
12399
|
const verification = await verifyVoiceOpsWebhookSignature({
|
|
@@ -14334,6 +14558,8 @@ export {
|
|
|
14334
14558
|
startVoiceOpsTask,
|
|
14335
14559
|
shapeTelephonyAssistantText,
|
|
14336
14560
|
selectVoiceTraceEventsForPrune,
|
|
14561
|
+
runVoiceToolContractSuite,
|
|
14562
|
+
runVoiceToolContract,
|
|
14337
14563
|
runVoiceSessionEvals,
|
|
14338
14564
|
runVoiceScenarioFixtureEvals,
|
|
14339
14565
|
runVoiceScenarioEvals,
|
|
@@ -14354,6 +14580,7 @@ export {
|
|
|
14354
14580
|
reopenVoiceOpsTask,
|
|
14355
14581
|
renderVoiceTraceMarkdown,
|
|
14356
14582
|
renderVoiceTraceHTML,
|
|
14583
|
+
renderVoiceToolContractHTML,
|
|
14357
14584
|
renderVoiceSessionsHTML,
|
|
14358
14585
|
renderVoiceScenarioFixtureEvalHTML,
|
|
14359
14586
|
renderVoiceScenarioEvalHTML,
|
|
@@ -14412,8 +14639,13 @@ export {
|
|
|
14412
14639
|
createVoiceTraceHTTPSink,
|
|
14413
14640
|
createVoiceTraceEventId,
|
|
14414
14641
|
createVoiceTraceEvent,
|
|
14642
|
+
createVoiceToolRuntimeContractDefaults,
|
|
14415
14643
|
createVoiceToolRuntime,
|
|
14416
14644
|
createVoiceToolIdempotencyKey,
|
|
14645
|
+
createVoiceToolContractRoutes,
|
|
14646
|
+
createVoiceToolContractJSONHandler,
|
|
14647
|
+
createVoiceToolContractHTMLHandler,
|
|
14648
|
+
createVoiceToolContract,
|
|
14417
14649
|
createVoiceTaskUpdatedEvent,
|
|
14418
14650
|
createVoiceTaskSLABreachedEvent,
|
|
14419
14651
|
createVoiceTaskCreatedEvent,
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Elysia } from 'elysia';
|
|
2
|
+
import type { VoiceAgentTool } from './agent';
|
|
3
|
+
import { type VoiceToolRuntimeOptions } from './toolRuntime';
|
|
4
|
+
import type { VoiceSessionRecord, VoiceTurnRecord } from './types';
|
|
5
|
+
export type VoiceToolContractExpectation = {
|
|
6
|
+
expectedAttempts?: number;
|
|
7
|
+
expectedErrorIncludes?: string;
|
|
8
|
+
expectedResult?: unknown;
|
|
9
|
+
expectIdempotent?: boolean;
|
|
10
|
+
expectStatus?: 'error' | 'ok';
|
|
11
|
+
expectTimedOut?: boolean;
|
|
12
|
+
maxElapsedMs?: number;
|
|
13
|
+
};
|
|
14
|
+
export type VoiceToolContractCase<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TArgs = Record<string, unknown>, TToolResult = unknown, TRouteResult = unknown> = {
|
|
15
|
+
args: TArgs;
|
|
16
|
+
context?: TContext;
|
|
17
|
+
expect?: VoiceToolContractExpectation;
|
|
18
|
+
id: string;
|
|
19
|
+
label?: string;
|
|
20
|
+
runtime?: VoiceToolRuntimeOptions<TContext, TSession, TRouteResult>;
|
|
21
|
+
session?: TSession;
|
|
22
|
+
toolCallId?: string;
|
|
23
|
+
turn?: VoiceTurnRecord;
|
|
24
|
+
};
|
|
25
|
+
export type VoiceToolContractDefinition<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TArgs = Record<string, unknown>, TToolResult = unknown, TRouteResult = unknown> = {
|
|
26
|
+
cases: Array<VoiceToolContractCase<TContext, TSession, TArgs, TToolResult, TRouteResult>>;
|
|
27
|
+
defaultRuntime?: VoiceToolRuntimeOptions<TContext, TSession, TRouteResult>;
|
|
28
|
+
description?: string;
|
|
29
|
+
id: string;
|
|
30
|
+
label?: string;
|
|
31
|
+
tool: VoiceAgentTool<TContext, TSession, TArgs, TToolResult, TRouteResult>;
|
|
32
|
+
};
|
|
33
|
+
export type VoiceToolContractIssue = {
|
|
34
|
+
caseId: string;
|
|
35
|
+
code: string;
|
|
36
|
+
message: string;
|
|
37
|
+
};
|
|
38
|
+
export type VoiceToolContractCaseReport = {
|
|
39
|
+
attempts: number;
|
|
40
|
+
caseId: string;
|
|
41
|
+
elapsedMs: number;
|
|
42
|
+
error?: string;
|
|
43
|
+
issues: VoiceToolContractIssue[];
|
|
44
|
+
label?: string;
|
|
45
|
+
pass: boolean;
|
|
46
|
+
status: 'error' | 'ok';
|
|
47
|
+
timedOut: boolean;
|
|
48
|
+
};
|
|
49
|
+
export type VoiceToolContractReport = {
|
|
50
|
+
cases: VoiceToolContractCaseReport[];
|
|
51
|
+
contractId: string;
|
|
52
|
+
label?: string;
|
|
53
|
+
issues: VoiceToolContractIssue[];
|
|
54
|
+
pass: boolean;
|
|
55
|
+
toolName: string;
|
|
56
|
+
};
|
|
57
|
+
export type VoiceToolContractSuiteReport = {
|
|
58
|
+
checkedAt: number;
|
|
59
|
+
contracts: VoiceToolContractReport[];
|
|
60
|
+
failed: number;
|
|
61
|
+
passed: number;
|
|
62
|
+
status: 'fail' | 'pass';
|
|
63
|
+
total: number;
|
|
64
|
+
};
|
|
65
|
+
export type VoiceToolContractHandlerOptions = {
|
|
66
|
+
contracts: VoiceToolContractDefinition[];
|
|
67
|
+
};
|
|
68
|
+
export type VoiceToolContractHTMLHandlerOptions = VoiceToolContractHandlerOptions & {
|
|
69
|
+
headers?: HeadersInit;
|
|
70
|
+
render?: (report: VoiceToolContractSuiteReport) => string | Promise<string>;
|
|
71
|
+
title?: string;
|
|
72
|
+
};
|
|
73
|
+
export type VoiceToolContractRoutesOptions = VoiceToolContractHTMLHandlerOptions & {
|
|
74
|
+
htmlPath?: false | string;
|
|
75
|
+
name?: string;
|
|
76
|
+
path?: string;
|
|
77
|
+
};
|
|
78
|
+
export declare const runVoiceToolContract: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TArgs = Record<string, unknown>, TToolResult = unknown, TRouteResult = unknown>(definition: VoiceToolContractDefinition<TContext, TSession, TArgs, TToolResult, TRouteResult>) => Promise<VoiceToolContractReport>;
|
|
79
|
+
export declare const createVoiceToolContract: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TArgs = Record<string, unknown>, TToolResult = unknown, TRouteResult = unknown>(definition: VoiceToolContractDefinition<TContext, TSession, TArgs, TToolResult, TRouteResult>) => {
|
|
80
|
+
assert: () => Promise<VoiceToolContractReport>;
|
|
81
|
+
definition: VoiceToolContractDefinition<TContext, TSession, TArgs, TToolResult, TRouteResult>;
|
|
82
|
+
run: () => Promise<VoiceToolContractReport>;
|
|
83
|
+
};
|
|
84
|
+
export declare const createVoiceToolRuntimeContractDefaults: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TRouteResult = unknown>() => VoiceToolRuntimeOptions<TContext, TSession, TRouteResult>;
|
|
85
|
+
export declare const runVoiceToolContractSuite: (options: VoiceToolContractHandlerOptions) => Promise<VoiceToolContractSuiteReport>;
|
|
86
|
+
export declare const renderVoiceToolContractHTML: (report: VoiceToolContractSuiteReport, options?: {
|
|
87
|
+
title?: string;
|
|
88
|
+
}) => string;
|
|
89
|
+
export declare const createVoiceToolContractJSONHandler: (options: VoiceToolContractHandlerOptions) => () => Promise<VoiceToolContractSuiteReport>;
|
|
90
|
+
export declare const createVoiceToolContractHTMLHandler: (options: VoiceToolContractHTMLHandlerOptions) => () => Promise<Response>;
|
|
91
|
+
export declare const createVoiceToolContractRoutes: (options: VoiceToolContractRoutesOptions) => Elysia<"", {
|
|
92
|
+
decorator: {};
|
|
93
|
+
store: {};
|
|
94
|
+
derive: {};
|
|
95
|
+
resolve: {};
|
|
96
|
+
}, {
|
|
97
|
+
typebox: {};
|
|
98
|
+
error: {};
|
|
99
|
+
}, {
|
|
100
|
+
schema: {};
|
|
101
|
+
standaloneSchema: {};
|
|
102
|
+
macro: {};
|
|
103
|
+
macroFn: {};
|
|
104
|
+
parser: {};
|
|
105
|
+
response: {};
|
|
106
|
+
}, {
|
|
107
|
+
[x: string]: {
|
|
108
|
+
get: {
|
|
109
|
+
body: unknown;
|
|
110
|
+
params: {};
|
|
111
|
+
query: unknown;
|
|
112
|
+
headers: unknown;
|
|
113
|
+
response: {
|
|
114
|
+
200: VoiceToolContractSuiteReport;
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
}, {
|
|
119
|
+
derive: {};
|
|
120
|
+
resolve: {};
|
|
121
|
+
schema: {};
|
|
122
|
+
standaloneSchema: {};
|
|
123
|
+
response: {};
|
|
124
|
+
}, {
|
|
125
|
+
derive: {};
|
|
126
|
+
resolve: {};
|
|
127
|
+
schema: {};
|
|
128
|
+
standaloneSchema: {};
|
|
129
|
+
response: {};
|
|
130
|
+
}>;
|