@absolutejs/voice 0.0.22-beta.4 → 0.0.22-beta.6
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/index.d.ts +2 -0
- package/dist/index.js +566 -0
- package/dist/modelAdapters.d.ts +39 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { createVoiceAssistant, createVoiceExperiment, summarizeVoiceAssistantRun
|
|
|
3
3
|
export { createVoiceAgent, createVoiceAgentSquad, createVoiceAgentTool } from './agent';
|
|
4
4
|
export { createStoredVoiceCallReviewArtifact, createStoredVoiceExternalObjectMap, createStoredVoiceIntegrationEvent, createStoredVoiceOpsTask, createVoiceFileExternalObjectMapStore, createVoiceFileAssistantMemoryStore, createVoiceFileIntegrationEventStore, createVoiceFileReviewStore, createVoiceFileRuntimeStorage, createVoiceFileSessionStore, createVoiceFileTaskStore, createVoiceFileTraceSinkDeliveryStore, createVoiceFileTraceEventStore } from './fileStore';
|
|
5
5
|
export { createVoiceAssistantMemoryHandle, createVoiceAssistantMemoryRecord, createVoiceMemoryAssistantMemoryStore, resolveVoiceAssistantMemoryNamespace } from './assistantMemory';
|
|
6
|
+
export { createAnthropicVoiceAssistantModel, createGeminiVoiceAssistantModel, createJSONVoiceAssistantModel, createOpenAIVoiceAssistantModel } from './modelAdapters';
|
|
6
7
|
export { buildVoiceTraceReplay, createVoiceMemoryTraceSinkDeliveryStore, createVoiceTraceHTTPSink, createVoiceMemoryTraceEventStore, createVoiceTraceSinkDeliveryId, createVoiceTraceSinkDeliveryRecord, createVoiceTraceSinkStore, createVoiceTraceEvent, createVoiceTraceEventId, deliverVoiceTraceEventsToSinks, evaluateVoiceTrace, exportVoiceTrace, filterVoiceTraceEvents, pruneVoiceTraceEvents, redactVoiceTraceEvent, redactVoiceTraceEvents, redactVoiceTraceText, renderVoiceTraceHTML, renderVoiceTraceMarkdown, resolveVoiceTraceRedactionOptions, selectVoiceTraceEventsForPrune, summarizeVoiceTrace } from './trace';
|
|
7
8
|
export { createVoiceSQLiteExternalObjectMapStore, createVoiceSQLiteIntegrationEventStore, createVoiceSQLiteReviewStore, createVoiceSQLiteRuntimeStorage, createVoiceSQLiteSessionStore, createVoiceSQLiteTaskStore, createVoiceSQLiteTraceSinkDeliveryStore, createVoiceSQLiteTraceEventStore } from './sqliteStore';
|
|
8
9
|
export { createVoicePostgresExternalObjectMapStore, createVoicePostgresIntegrationEventStore, createVoicePostgresReviewStore, createVoicePostgresRuntimeStorage, createVoicePostgresSessionStore, createVoicePostgresTaskStore, createVoicePostgresTraceSinkDeliveryStore, createVoicePostgresTraceEventStore } from './postgresStore';
|
|
@@ -25,6 +26,7 @@ export { resolveTurnDetectionConfig, TURN_PROFILE_DEFAULTS } from './turnProfile
|
|
|
25
26
|
export { createVoiceCallReviewFromLiveTelephonyReport, createVoiceCallReviewRecorder, renderVoiceCallReviewHTML, renderVoiceCallReviewMarkdown } from './testing/review';
|
|
26
27
|
export type { VoiceAssistant, VoiceAssistantArtifactPlan, VoiceAssistantExperiment, VoiceAssistantExperimentOptions, VoiceAssistantGuardrailInput, VoiceAssistantGuardrails, VoiceAssistantMemoryLifecycle, VoiceAssistantMemoryLifecycleInput, VoiceAssistantOptions, VoiceAssistantOutputGuardrailInput, VoiceAssistantPreset, VoiceAssistantRunsSummary, VoiceAssistantRunSummary, VoiceAssistantVariant } from './assistant';
|
|
27
28
|
export type { VoiceAssistantMemoryBinding, VoiceAssistantMemoryHandle, VoiceAssistantMemoryOptions, VoiceAssistantMemoryRecord, VoiceAssistantMemoryStore } from './assistantMemory';
|
|
29
|
+
export type { AnthropicVoiceAssistantModelOptions, GeminiVoiceAssistantModelOptions, OpenAIVoiceAssistantModelOptions, VoiceJSONAssistantModelHandler, VoiceJSONAssistantModelOptions } from './modelAdapters';
|
|
28
30
|
export type { VoiceAgent, VoiceAgentMessage, VoiceAgentMessageRole, VoiceAgentModel, VoiceAgentModelInput, VoiceAgentModelOutput, VoiceAgentOptions, VoiceAgentRunResult, VoiceAgentSquadOptions, VoiceAgentTool, VoiceAgentToolCall, VoiceAgentToolResult } from './agent';
|
|
29
31
|
export type { VoiceOpsRuntime, VoiceOpsRuntimeConfig, VoiceOpsRuntimeSummary, VoiceOpsRuntimeSinkWorkerConfig, VoiceOpsRuntimeTaskWorkerConfig, VoiceOpsRuntimeTickResult, VoiceOpsRuntimeWebhookWorkerConfig } from './opsRuntime';
|
|
30
32
|
export type { VoiceOpsPresetName, VoiceOpsPresetOverrides, VoiceResolvedOpsPreset } from './opsPresets';
|
package/dist/index.js
CHANGED
|
@@ -5150,6 +5150,17 @@ var createVoiceAgent = (options) => {
|
|
|
5150
5150
|
if (output.assistantText?.trim()) {
|
|
5151
5151
|
messages.push({
|
|
5152
5152
|
content: output.assistantText,
|
|
5153
|
+
metadata: output.toolCalls?.length ? {
|
|
5154
|
+
toolCalls: output.toolCalls
|
|
5155
|
+
} : undefined,
|
|
5156
|
+
role: "assistant"
|
|
5157
|
+
});
|
|
5158
|
+
} else if (output.toolCalls?.length) {
|
|
5159
|
+
messages.push({
|
|
5160
|
+
content: "",
|
|
5161
|
+
metadata: {
|
|
5162
|
+
toolCalls: output.toolCalls
|
|
5163
|
+
},
|
|
5153
5164
|
role: "assistant"
|
|
5154
5165
|
});
|
|
5155
5166
|
}
|
|
@@ -7073,6 +7084,557 @@ var createStoredVoiceExternalObjectMap = (mapping) => createVoiceExternalObjectM
|
|
|
7073
7084
|
sourceId: mapping.sourceId,
|
|
7074
7085
|
sourceType: mapping.sourceType
|
|
7075
7086
|
});
|
|
7087
|
+
// src/modelAdapters.ts
|
|
7088
|
+
var OUTPUT_SCHEMA = {
|
|
7089
|
+
additionalProperties: false,
|
|
7090
|
+
properties: {
|
|
7091
|
+
assistantText: {
|
|
7092
|
+
type: "string"
|
|
7093
|
+
},
|
|
7094
|
+
complete: {
|
|
7095
|
+
type: "boolean"
|
|
7096
|
+
},
|
|
7097
|
+
escalate: {
|
|
7098
|
+
additionalProperties: false,
|
|
7099
|
+
properties: {
|
|
7100
|
+
metadata: {
|
|
7101
|
+
additionalProperties: true,
|
|
7102
|
+
type: "object"
|
|
7103
|
+
},
|
|
7104
|
+
reason: {
|
|
7105
|
+
type: "string"
|
|
7106
|
+
}
|
|
7107
|
+
},
|
|
7108
|
+
required: ["reason"],
|
|
7109
|
+
type: "object"
|
|
7110
|
+
},
|
|
7111
|
+
noAnswer: {
|
|
7112
|
+
additionalProperties: false,
|
|
7113
|
+
properties: {
|
|
7114
|
+
metadata: {
|
|
7115
|
+
additionalProperties: true,
|
|
7116
|
+
type: "object"
|
|
7117
|
+
}
|
|
7118
|
+
},
|
|
7119
|
+
type: "object"
|
|
7120
|
+
},
|
|
7121
|
+
result: {
|
|
7122
|
+
additionalProperties: true,
|
|
7123
|
+
type: "object"
|
|
7124
|
+
},
|
|
7125
|
+
transfer: {
|
|
7126
|
+
additionalProperties: false,
|
|
7127
|
+
properties: {
|
|
7128
|
+
metadata: {
|
|
7129
|
+
additionalProperties: true,
|
|
7130
|
+
type: "object"
|
|
7131
|
+
},
|
|
7132
|
+
reason: {
|
|
7133
|
+
type: "string"
|
|
7134
|
+
},
|
|
7135
|
+
target: {
|
|
7136
|
+
type: "string"
|
|
7137
|
+
}
|
|
7138
|
+
},
|
|
7139
|
+
required: ["target"],
|
|
7140
|
+
type: "object"
|
|
7141
|
+
},
|
|
7142
|
+
voicemail: {
|
|
7143
|
+
additionalProperties: false,
|
|
7144
|
+
properties: {
|
|
7145
|
+
metadata: {
|
|
7146
|
+
additionalProperties: true,
|
|
7147
|
+
type: "object"
|
|
7148
|
+
}
|
|
7149
|
+
},
|
|
7150
|
+
type: "object"
|
|
7151
|
+
}
|
|
7152
|
+
},
|
|
7153
|
+
type: "object"
|
|
7154
|
+
};
|
|
7155
|
+
var ROUTE_RESULT_INSTRUCTION = "Return a JSON object with assistantText, complete, transfer, escalate, voicemail, noAnswer, and result when you are not calling tools.";
|
|
7156
|
+
var parseJSON = (value) => {
|
|
7157
|
+
try {
|
|
7158
|
+
const parsed = JSON.parse(value);
|
|
7159
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
7160
|
+
} catch {
|
|
7161
|
+
return {
|
|
7162
|
+
assistantText: value
|
|
7163
|
+
};
|
|
7164
|
+
}
|
|
7165
|
+
};
|
|
7166
|
+
var parseJSONValue = (value) => {
|
|
7167
|
+
try {
|
|
7168
|
+
return JSON.parse(value);
|
|
7169
|
+
} catch {
|
|
7170
|
+
return value;
|
|
7171
|
+
}
|
|
7172
|
+
};
|
|
7173
|
+
var getMessageToolCalls = (message) => {
|
|
7174
|
+
const toolCalls = message.metadata?.toolCalls;
|
|
7175
|
+
return Array.isArray(toolCalls) ? toolCalls.filter((toolCall) => toolCall && typeof toolCall === "object" && typeof toolCall.name === "string") : [];
|
|
7176
|
+
};
|
|
7177
|
+
var createHTTPError = (provider, response) => new Error(`${provider} voice assistant model failed: HTTP ${response.status}`);
|
|
7178
|
+
var normalizeRouteOutput = (output) => {
|
|
7179
|
+
const result = {};
|
|
7180
|
+
if (typeof output.assistantText === "string") {
|
|
7181
|
+
result.assistantText = output.assistantText;
|
|
7182
|
+
}
|
|
7183
|
+
if (typeof output.complete === "boolean") {
|
|
7184
|
+
result.complete = output.complete;
|
|
7185
|
+
}
|
|
7186
|
+
if (output.result !== undefined) {
|
|
7187
|
+
result.result = output.result;
|
|
7188
|
+
}
|
|
7189
|
+
if (output.transfer && typeof output.transfer === "object") {
|
|
7190
|
+
const transfer = output.transfer;
|
|
7191
|
+
if (typeof transfer.target === "string") {
|
|
7192
|
+
result.transfer = {
|
|
7193
|
+
metadata: transfer.metadata && typeof transfer.metadata === "object" ? transfer.metadata : undefined,
|
|
7194
|
+
reason: typeof transfer.reason === "string" ? transfer.reason : undefined,
|
|
7195
|
+
target: transfer.target
|
|
7196
|
+
};
|
|
7197
|
+
}
|
|
7198
|
+
}
|
|
7199
|
+
if (output.escalate && typeof output.escalate === "object") {
|
|
7200
|
+
const escalate = output.escalate;
|
|
7201
|
+
if (typeof escalate.reason === "string") {
|
|
7202
|
+
result.escalate = {
|
|
7203
|
+
metadata: escalate.metadata && typeof escalate.metadata === "object" ? escalate.metadata : undefined,
|
|
7204
|
+
reason: escalate.reason
|
|
7205
|
+
};
|
|
7206
|
+
}
|
|
7207
|
+
}
|
|
7208
|
+
if (output.voicemail && typeof output.voicemail === "object") {
|
|
7209
|
+
const voicemail = output.voicemail;
|
|
7210
|
+
result.voicemail = {
|
|
7211
|
+
metadata: voicemail.metadata && typeof voicemail.metadata === "object" ? voicemail.metadata : undefined
|
|
7212
|
+
};
|
|
7213
|
+
}
|
|
7214
|
+
if (output.noAnswer && typeof output.noAnswer === "object") {
|
|
7215
|
+
const noAnswer = output.noAnswer;
|
|
7216
|
+
result.noAnswer = {
|
|
7217
|
+
metadata: noAnswer.metadata && typeof noAnswer.metadata === "object" ? noAnswer.metadata : undefined
|
|
7218
|
+
};
|
|
7219
|
+
}
|
|
7220
|
+
return result;
|
|
7221
|
+
};
|
|
7222
|
+
var createJSONVoiceAssistantModel = (options) => ({
|
|
7223
|
+
generate: async (input) => {
|
|
7224
|
+
const output = await options.generate(input);
|
|
7225
|
+
if ("assistantText" in output || "toolCalls" in output || "complete" in output || "transfer" in output || "escalate" in output) {
|
|
7226
|
+
return output;
|
|
7227
|
+
}
|
|
7228
|
+
return options.mapOutput?.(output) ?? normalizeRouteOutput(output);
|
|
7229
|
+
}
|
|
7230
|
+
});
|
|
7231
|
+
var messageToOpenAIInput = (message) => {
|
|
7232
|
+
if (message.role === "tool") {
|
|
7233
|
+
return {
|
|
7234
|
+
call_id: message.toolCallId ?? message.name ?? crypto.randomUUID(),
|
|
7235
|
+
output: message.content,
|
|
7236
|
+
type: "function_call_output"
|
|
7237
|
+
};
|
|
7238
|
+
}
|
|
7239
|
+
return {
|
|
7240
|
+
content: message.content,
|
|
7241
|
+
role: message.role === "system" ? "developer" : message.role
|
|
7242
|
+
};
|
|
7243
|
+
};
|
|
7244
|
+
var messageToAnthropicMessage = (message) => {
|
|
7245
|
+
if (message.role === "system") {
|
|
7246
|
+
return;
|
|
7247
|
+
}
|
|
7248
|
+
if (message.role === "tool") {
|
|
7249
|
+
if (!message.toolCallId) {
|
|
7250
|
+
return {
|
|
7251
|
+
content: `Tool result from ${message.name ?? "tool"}: ${message.content}`,
|
|
7252
|
+
role: "user"
|
|
7253
|
+
};
|
|
7254
|
+
}
|
|
7255
|
+
return {
|
|
7256
|
+
content: [
|
|
7257
|
+
{
|
|
7258
|
+
content: message.content,
|
|
7259
|
+
tool_use_id: message.toolCallId,
|
|
7260
|
+
type: "tool_result"
|
|
7261
|
+
}
|
|
7262
|
+
],
|
|
7263
|
+
role: "user"
|
|
7264
|
+
};
|
|
7265
|
+
}
|
|
7266
|
+
const toolCalls = getMessageToolCalls(message);
|
|
7267
|
+
if (message.role === "assistant" && toolCalls.length) {
|
|
7268
|
+
return {
|
|
7269
|
+
content: [
|
|
7270
|
+
...message.content ? [
|
|
7271
|
+
{
|
|
7272
|
+
text: message.content,
|
|
7273
|
+
type: "text"
|
|
7274
|
+
}
|
|
7275
|
+
] : [],
|
|
7276
|
+
...toolCalls.map((toolCall) => ({
|
|
7277
|
+
id: toolCall.id ?? crypto.randomUUID(),
|
|
7278
|
+
input: toolCall.args,
|
|
7279
|
+
name: toolCall.name,
|
|
7280
|
+
type: "tool_use"
|
|
7281
|
+
}))
|
|
7282
|
+
],
|
|
7283
|
+
role: "assistant"
|
|
7284
|
+
};
|
|
7285
|
+
}
|
|
7286
|
+
return {
|
|
7287
|
+
content: message.content,
|
|
7288
|
+
role: message.role
|
|
7289
|
+
};
|
|
7290
|
+
};
|
|
7291
|
+
var toGeminiSchema = (schema) => {
|
|
7292
|
+
const next = {};
|
|
7293
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
7294
|
+
if (key === "additionalProperties") {
|
|
7295
|
+
continue;
|
|
7296
|
+
}
|
|
7297
|
+
if (key === "type" && typeof value === "string") {
|
|
7298
|
+
next[key] = value.toUpperCase();
|
|
7299
|
+
continue;
|
|
7300
|
+
}
|
|
7301
|
+
if (Array.isArray(value)) {
|
|
7302
|
+
next[key] = value.map((item) => item && typeof item === "object" ? toGeminiSchema(item) : item);
|
|
7303
|
+
continue;
|
|
7304
|
+
}
|
|
7305
|
+
if (value && typeof value === "object") {
|
|
7306
|
+
next[key] = toGeminiSchema(value);
|
|
7307
|
+
continue;
|
|
7308
|
+
}
|
|
7309
|
+
next[key] = value;
|
|
7310
|
+
}
|
|
7311
|
+
return next;
|
|
7312
|
+
};
|
|
7313
|
+
var messageToGeminiContent = (message) => {
|
|
7314
|
+
if (message.role === "system") {
|
|
7315
|
+
return;
|
|
7316
|
+
}
|
|
7317
|
+
if (message.role === "tool") {
|
|
7318
|
+
return {
|
|
7319
|
+
parts: [
|
|
7320
|
+
{
|
|
7321
|
+
functionResponse: {
|
|
7322
|
+
id: message.toolCallId,
|
|
7323
|
+
name: message.name ?? "tool",
|
|
7324
|
+
response: {
|
|
7325
|
+
result: parseJSONValue(message.content)
|
|
7326
|
+
}
|
|
7327
|
+
}
|
|
7328
|
+
}
|
|
7329
|
+
],
|
|
7330
|
+
role: "user"
|
|
7331
|
+
};
|
|
7332
|
+
}
|
|
7333
|
+
const toolCalls = getMessageToolCalls(message);
|
|
7334
|
+
if (message.role === "assistant" && toolCalls.length) {
|
|
7335
|
+
return {
|
|
7336
|
+
parts: [
|
|
7337
|
+
...message.content ? [
|
|
7338
|
+
{
|
|
7339
|
+
text: message.content
|
|
7340
|
+
}
|
|
7341
|
+
] : [],
|
|
7342
|
+
...toolCalls.map((toolCall) => ({
|
|
7343
|
+
functionCall: {
|
|
7344
|
+
args: toolCall.args,
|
|
7345
|
+
id: toolCall.id,
|
|
7346
|
+
name: toolCall.name
|
|
7347
|
+
}
|
|
7348
|
+
}))
|
|
7349
|
+
],
|
|
7350
|
+
role: "model"
|
|
7351
|
+
};
|
|
7352
|
+
}
|
|
7353
|
+
return {
|
|
7354
|
+
parts: [
|
|
7355
|
+
{
|
|
7356
|
+
text: message.content
|
|
7357
|
+
}
|
|
7358
|
+
],
|
|
7359
|
+
role: message.role === "assistant" ? "model" : "user"
|
|
7360
|
+
};
|
|
7361
|
+
};
|
|
7362
|
+
var extractText = (response) => {
|
|
7363
|
+
if (typeof response.output_text === "string") {
|
|
7364
|
+
return response.output_text;
|
|
7365
|
+
}
|
|
7366
|
+
const output = Array.isArray(response.output) ? response.output : [];
|
|
7367
|
+
for (const item of output) {
|
|
7368
|
+
if (!item || typeof item !== "object") {
|
|
7369
|
+
continue;
|
|
7370
|
+
}
|
|
7371
|
+
const record = item;
|
|
7372
|
+
const content = Array.isArray(record.content) ? record.content : [];
|
|
7373
|
+
for (const contentItem of content) {
|
|
7374
|
+
if (!contentItem || typeof contentItem !== "object") {
|
|
7375
|
+
continue;
|
|
7376
|
+
}
|
|
7377
|
+
const contentRecord = contentItem;
|
|
7378
|
+
if (typeof contentRecord.text === "string") {
|
|
7379
|
+
return contentRecord.text;
|
|
7380
|
+
}
|
|
7381
|
+
}
|
|
7382
|
+
}
|
|
7383
|
+
return "";
|
|
7384
|
+
};
|
|
7385
|
+
var extractToolCalls = (response) => {
|
|
7386
|
+
const output = Array.isArray(response.output) ? response.output : [];
|
|
7387
|
+
const toolCalls = [];
|
|
7388
|
+
for (const item of output) {
|
|
7389
|
+
if (!item || typeof item !== "object") {
|
|
7390
|
+
continue;
|
|
7391
|
+
}
|
|
7392
|
+
const record = item;
|
|
7393
|
+
if (record.type !== "function_call" || typeof record.name !== "string") {
|
|
7394
|
+
continue;
|
|
7395
|
+
}
|
|
7396
|
+
const args = typeof record.arguments === "string" ? parseJSON(record.arguments) : {};
|
|
7397
|
+
toolCalls.push({
|
|
7398
|
+
args,
|
|
7399
|
+
id: typeof record.call_id === "string" ? record.call_id : typeof record.id === "string" ? record.id : undefined,
|
|
7400
|
+
name: record.name
|
|
7401
|
+
});
|
|
7402
|
+
}
|
|
7403
|
+
return toolCalls;
|
|
7404
|
+
};
|
|
7405
|
+
var createOpenAIVoiceAssistantModel = (options) => {
|
|
7406
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
7407
|
+
const baseUrl = options.baseUrl ?? "https://api.openai.com/v1";
|
|
7408
|
+
const model = options.model ?? "gpt-4.1-mini";
|
|
7409
|
+
return {
|
|
7410
|
+
generate: async (input) => {
|
|
7411
|
+
const response = await fetchImpl(`${baseUrl.replace(/\/$/, "")}/responses`, {
|
|
7412
|
+
body: JSON.stringify({
|
|
7413
|
+
input: input.messages.map(messageToOpenAIInput),
|
|
7414
|
+
instructions: [
|
|
7415
|
+
input.system,
|
|
7416
|
+
"Return a JSON object with assistantText, complete, transfer, escalate, voicemail, noAnswer, and result when you are not calling tools."
|
|
7417
|
+
].filter(Boolean).join(`
|
|
7418
|
+
|
|
7419
|
+
`),
|
|
7420
|
+
max_output_tokens: options.maxOutputTokens,
|
|
7421
|
+
model,
|
|
7422
|
+
temperature: options.temperature,
|
|
7423
|
+
text: {
|
|
7424
|
+
format: {
|
|
7425
|
+
name: "voice_route_result",
|
|
7426
|
+
schema: OUTPUT_SCHEMA,
|
|
7427
|
+
strict: false,
|
|
7428
|
+
type: "json_schema"
|
|
7429
|
+
}
|
|
7430
|
+
},
|
|
7431
|
+
tool_choice: input.tools.length ? "auto" : "none",
|
|
7432
|
+
tools: input.tools.map((tool) => ({
|
|
7433
|
+
description: tool.description,
|
|
7434
|
+
name: tool.name,
|
|
7435
|
+
parameters: tool.parameters ?? {
|
|
7436
|
+
additionalProperties: true,
|
|
7437
|
+
type: "object"
|
|
7438
|
+
},
|
|
7439
|
+
strict: false,
|
|
7440
|
+
type: "function"
|
|
7441
|
+
}))
|
|
7442
|
+
}),
|
|
7443
|
+
headers: {
|
|
7444
|
+
authorization: `Bearer ${options.apiKey}`,
|
|
7445
|
+
"content-type": "application/json"
|
|
7446
|
+
},
|
|
7447
|
+
method: "POST"
|
|
7448
|
+
});
|
|
7449
|
+
if (!response.ok) {
|
|
7450
|
+
throw createHTTPError("OpenAI", response);
|
|
7451
|
+
}
|
|
7452
|
+
const body = await response.json();
|
|
7453
|
+
if (body.usage && typeof body.usage === "object") {
|
|
7454
|
+
await options.onUsage?.(body.usage);
|
|
7455
|
+
}
|
|
7456
|
+
const toolCalls = extractToolCalls(body);
|
|
7457
|
+
if (toolCalls.length) {
|
|
7458
|
+
return {
|
|
7459
|
+
toolCalls
|
|
7460
|
+
};
|
|
7461
|
+
}
|
|
7462
|
+
return normalizeRouteOutput(parseJSON(extractText(body)));
|
|
7463
|
+
}
|
|
7464
|
+
};
|
|
7465
|
+
};
|
|
7466
|
+
var extractAnthropicText = (response) => {
|
|
7467
|
+
const content = Array.isArray(response.content) ? response.content : [];
|
|
7468
|
+
return content.map((item) => item && typeof item === "object" && item.type === "text" && typeof item.text === "string" ? item.text : "").filter(Boolean).join(`
|
|
7469
|
+
`);
|
|
7470
|
+
};
|
|
7471
|
+
var extractAnthropicToolCalls = (response) => {
|
|
7472
|
+
const content = Array.isArray(response.content) ? response.content : [];
|
|
7473
|
+
const toolCalls = [];
|
|
7474
|
+
for (const item of content) {
|
|
7475
|
+
if (!item || typeof item !== "object") {
|
|
7476
|
+
continue;
|
|
7477
|
+
}
|
|
7478
|
+
const record = item;
|
|
7479
|
+
if (record.type !== "tool_use" || typeof record.name !== "string") {
|
|
7480
|
+
continue;
|
|
7481
|
+
}
|
|
7482
|
+
toolCalls.push({
|
|
7483
|
+
args: record.input && typeof record.input === "object" ? record.input : {},
|
|
7484
|
+
id: typeof record.id === "string" ? record.id : undefined,
|
|
7485
|
+
name: record.name
|
|
7486
|
+
});
|
|
7487
|
+
}
|
|
7488
|
+
return toolCalls;
|
|
7489
|
+
};
|
|
7490
|
+
var createAnthropicVoiceAssistantModel = (options) => {
|
|
7491
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
7492
|
+
const baseUrl = options.baseUrl ?? "https://api.anthropic.com/v1";
|
|
7493
|
+
const model = options.model ?? "claude-sonnet-4-5";
|
|
7494
|
+
return {
|
|
7495
|
+
generate: async (input) => {
|
|
7496
|
+
const response = await fetchImpl(`${baseUrl.replace(/\/$/, "")}/messages`, {
|
|
7497
|
+
body: JSON.stringify({
|
|
7498
|
+
max_tokens: options.maxOutputTokens ?? 1024,
|
|
7499
|
+
messages: input.messages.map(messageToAnthropicMessage).filter(Boolean),
|
|
7500
|
+
model,
|
|
7501
|
+
system: [input.system, ROUTE_RESULT_INSTRUCTION].filter(Boolean).join(`
|
|
7502
|
+
|
|
7503
|
+
`),
|
|
7504
|
+
temperature: options.temperature,
|
|
7505
|
+
tool_choice: input.tools.length ? { type: "auto" } : { type: "none" },
|
|
7506
|
+
tools: input.tools.map((tool) => ({
|
|
7507
|
+
description: tool.description,
|
|
7508
|
+
input_schema: tool.parameters ?? {
|
|
7509
|
+
additionalProperties: true,
|
|
7510
|
+
type: "object"
|
|
7511
|
+
},
|
|
7512
|
+
name: tool.name
|
|
7513
|
+
}))
|
|
7514
|
+
}),
|
|
7515
|
+
headers: {
|
|
7516
|
+
"anthropic-version": options.version ?? "2023-06-01",
|
|
7517
|
+
"content-type": "application/json",
|
|
7518
|
+
"x-api-key": options.apiKey
|
|
7519
|
+
},
|
|
7520
|
+
method: "POST"
|
|
7521
|
+
});
|
|
7522
|
+
if (!response.ok) {
|
|
7523
|
+
throw createHTTPError("Anthropic", response);
|
|
7524
|
+
}
|
|
7525
|
+
const body = await response.json();
|
|
7526
|
+
if (body.usage && typeof body.usage === "object") {
|
|
7527
|
+
await options.onUsage?.(body.usage);
|
|
7528
|
+
}
|
|
7529
|
+
const toolCalls = extractAnthropicToolCalls(body);
|
|
7530
|
+
if (toolCalls.length) {
|
|
7531
|
+
return {
|
|
7532
|
+
assistantText: extractAnthropicText(body) || undefined,
|
|
7533
|
+
toolCalls
|
|
7534
|
+
};
|
|
7535
|
+
}
|
|
7536
|
+
return normalizeRouteOutput(parseJSON(extractAnthropicText(body)));
|
|
7537
|
+
}
|
|
7538
|
+
};
|
|
7539
|
+
};
|
|
7540
|
+
var extractGeminiCandidateParts = (response) => {
|
|
7541
|
+
const candidates = Array.isArray(response.candidates) ? response.candidates : [];
|
|
7542
|
+
const first = candidates[0];
|
|
7543
|
+
if (!first || typeof first !== "object") {
|
|
7544
|
+
return [];
|
|
7545
|
+
}
|
|
7546
|
+
const content = first.content;
|
|
7547
|
+
if (!content || typeof content !== "object") {
|
|
7548
|
+
return [];
|
|
7549
|
+
}
|
|
7550
|
+
const parts = content.parts;
|
|
7551
|
+
return Array.isArray(parts) ? parts : [];
|
|
7552
|
+
};
|
|
7553
|
+
var extractGeminiText = (response) => extractGeminiCandidateParts(response).map((part) => part && typeof part === "object" && typeof part.text === "string" ? part.text : "").filter(Boolean).join(`
|
|
7554
|
+
`);
|
|
7555
|
+
var extractGeminiToolCalls = (response) => {
|
|
7556
|
+
const toolCalls = [];
|
|
7557
|
+
for (const part of extractGeminiCandidateParts(response)) {
|
|
7558
|
+
if (!part || typeof part !== "object") {
|
|
7559
|
+
continue;
|
|
7560
|
+
}
|
|
7561
|
+
const functionCall = part.functionCall;
|
|
7562
|
+
if (!functionCall || typeof functionCall !== "object") {
|
|
7563
|
+
continue;
|
|
7564
|
+
}
|
|
7565
|
+
const record = functionCall;
|
|
7566
|
+
if (typeof record.name !== "string") {
|
|
7567
|
+
continue;
|
|
7568
|
+
}
|
|
7569
|
+
toolCalls.push({
|
|
7570
|
+
args: record.args && typeof record.args === "object" ? record.args : {},
|
|
7571
|
+
id: typeof record.id === "string" ? record.id : undefined,
|
|
7572
|
+
name: record.name
|
|
7573
|
+
});
|
|
7574
|
+
}
|
|
7575
|
+
return toolCalls;
|
|
7576
|
+
};
|
|
7577
|
+
var createGeminiVoiceAssistantModel = (options) => {
|
|
7578
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
7579
|
+
const baseUrl = options.baseUrl ?? "https://generativelanguage.googleapis.com/v1beta";
|
|
7580
|
+
const model = options.model ?? "gemini-2.5-flash";
|
|
7581
|
+
return {
|
|
7582
|
+
generate: async (input) => {
|
|
7583
|
+
const endpoint = `${baseUrl.replace(/\/$/, "")}/models/${encodeURIComponent(model)}:generateContent?key=${encodeURIComponent(options.apiKey)}`;
|
|
7584
|
+
const response = await fetchImpl(endpoint, {
|
|
7585
|
+
body: JSON.stringify({
|
|
7586
|
+
contents: input.messages.map(messageToGeminiContent).filter(Boolean),
|
|
7587
|
+
generationConfig: {
|
|
7588
|
+
maxOutputTokens: options.maxOutputTokens,
|
|
7589
|
+
responseMimeType: "application/json",
|
|
7590
|
+
responseSchema: toGeminiSchema(OUTPUT_SCHEMA),
|
|
7591
|
+
temperature: options.temperature
|
|
7592
|
+
},
|
|
7593
|
+
systemInstruction: {
|
|
7594
|
+
parts: [
|
|
7595
|
+
{
|
|
7596
|
+
text: [input.system, ROUTE_RESULT_INSTRUCTION].filter(Boolean).join(`
|
|
7597
|
+
|
|
7598
|
+
`)
|
|
7599
|
+
}
|
|
7600
|
+
]
|
|
7601
|
+
},
|
|
7602
|
+
tools: input.tools.length ? [
|
|
7603
|
+
{
|
|
7604
|
+
functionDeclarations: input.tools.map((tool) => ({
|
|
7605
|
+
description: tool.description,
|
|
7606
|
+
name: tool.name,
|
|
7607
|
+
parameters: toGeminiSchema(tool.parameters ?? {
|
|
7608
|
+
additionalProperties: true,
|
|
7609
|
+
type: "object"
|
|
7610
|
+
})
|
|
7611
|
+
}))
|
|
7612
|
+
}
|
|
7613
|
+
] : undefined
|
|
7614
|
+
}),
|
|
7615
|
+
headers: {
|
|
7616
|
+
"content-type": "application/json"
|
|
7617
|
+
},
|
|
7618
|
+
method: "POST"
|
|
7619
|
+
});
|
|
7620
|
+
if (!response.ok) {
|
|
7621
|
+
throw createHTTPError("Gemini", response);
|
|
7622
|
+
}
|
|
7623
|
+
const body = await response.json();
|
|
7624
|
+
if (body.usageMetadata && typeof body.usageMetadata === "object") {
|
|
7625
|
+
await options.onUsage?.(body.usageMetadata);
|
|
7626
|
+
}
|
|
7627
|
+
const toolCalls = extractGeminiToolCalls(body);
|
|
7628
|
+
if (toolCalls.length) {
|
|
7629
|
+
return {
|
|
7630
|
+
assistantText: extractGeminiText(body) || undefined,
|
|
7631
|
+
toolCalls
|
|
7632
|
+
};
|
|
7633
|
+
}
|
|
7634
|
+
return normalizeRouteOutput(parseJSON(extractGeminiText(body)));
|
|
7635
|
+
}
|
|
7636
|
+
};
|
|
7637
|
+
};
|
|
7076
7638
|
// src/sqliteStore.ts
|
|
7077
7639
|
import { Database } from "bun:sqlite";
|
|
7078
7640
|
var normalizeTableNameSegment = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice";
|
|
@@ -9658,9 +10220,13 @@ export {
|
|
|
9658
10220
|
createStoredVoiceCallReviewArtifact,
|
|
9659
10221
|
createRiskyTurnCorrectionHandler,
|
|
9660
10222
|
createPhraseHintCorrectionHandler,
|
|
10223
|
+
createOpenAIVoiceAssistantModel,
|
|
10224
|
+
createJSONVoiceAssistantModel,
|
|
9661
10225
|
createId,
|
|
10226
|
+
createGeminiVoiceAssistantModel,
|
|
9662
10227
|
createDomainPhraseHints,
|
|
9663
10228
|
createDomainLexicon,
|
|
10229
|
+
createAnthropicVoiceAssistantModel,
|
|
9664
10230
|
conditionAudioChunk,
|
|
9665
10231
|
completeVoiceOpsTask,
|
|
9666
10232
|
claimVoiceOpsTask,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { VoiceAgentModel, VoiceAgentModelInput, VoiceAgentModelOutput } from './agent';
|
|
2
|
+
import type { VoiceSessionRecord } from './types';
|
|
3
|
+
export type VoiceJSONAssistantModelHandler<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown> = (input: VoiceAgentModelInput<TContext, TSession>) => Promise<Record<string, unknown> | VoiceAgentModelOutput<TResult>> | Record<string, unknown> | VoiceAgentModelOutput<TResult>;
|
|
4
|
+
export type VoiceJSONAssistantModelOptions<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown> = {
|
|
5
|
+
generate: VoiceJSONAssistantModelHandler<TContext, TSession, TResult>;
|
|
6
|
+
mapOutput?: (output: Record<string, unknown>) => VoiceAgentModelOutput<TResult>;
|
|
7
|
+
};
|
|
8
|
+
export type OpenAIVoiceAssistantModelOptions = {
|
|
9
|
+
apiKey: string;
|
|
10
|
+
baseUrl?: string;
|
|
11
|
+
fetch?: typeof fetch;
|
|
12
|
+
maxOutputTokens?: number;
|
|
13
|
+
model?: string;
|
|
14
|
+
onUsage?: (usage: Record<string, unknown>) => Promise<void> | void;
|
|
15
|
+
temperature?: number;
|
|
16
|
+
};
|
|
17
|
+
export type AnthropicVoiceAssistantModelOptions = {
|
|
18
|
+
apiKey: string;
|
|
19
|
+
baseUrl?: string;
|
|
20
|
+
fetch?: typeof fetch;
|
|
21
|
+
maxOutputTokens?: number;
|
|
22
|
+
model?: string;
|
|
23
|
+
onUsage?: (usage: Record<string, unknown>) => Promise<void> | void;
|
|
24
|
+
temperature?: number;
|
|
25
|
+
version?: string;
|
|
26
|
+
};
|
|
27
|
+
export type GeminiVoiceAssistantModelOptions = {
|
|
28
|
+
apiKey: string;
|
|
29
|
+
baseUrl?: string;
|
|
30
|
+
fetch?: typeof fetch;
|
|
31
|
+
maxOutputTokens?: number;
|
|
32
|
+
model?: string;
|
|
33
|
+
onUsage?: (usage: Record<string, unknown>) => Promise<void> | void;
|
|
34
|
+
temperature?: number;
|
|
35
|
+
};
|
|
36
|
+
export declare const createJSONVoiceAssistantModel: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(options: VoiceJSONAssistantModelOptions<TContext, TSession, TResult>) => VoiceAgentModel<TContext, TSession, TResult>;
|
|
37
|
+
export declare const createOpenAIVoiceAssistantModel: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(options: OpenAIVoiceAssistantModelOptions) => VoiceAgentModel<TContext, TSession, TResult>;
|
|
38
|
+
export declare const createAnthropicVoiceAssistantModel: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(options: AnthropicVoiceAssistantModelOptions) => VoiceAgentModel<TContext, TSession, TResult>;
|
|
39
|
+
export declare const createGeminiVoiceAssistantModel: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(options: GeminiVoiceAssistantModelOptions) => VoiceAgentModel<TContext, TSession, TResult>;
|