@voicelayer/sdk 0.6.2 → 0.6.3
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/brain/index.d.ts +2 -2
- package/dist/index.d.ts +254 -254
- package/dist/index.js +1034 -654
- package/dist/runtime/text-session.d.ts +1 -1
- package/dist/runtime/text-session.js +468 -100
- package/dist/{text-session-B-T33y5P.d.ts → text-session-B928dhkB.d.ts} +108 -108
- package/package.json +7 -7
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { b1 as EmailResolver, b2 as FlowResolver, b3 as GraphResolvers, b4 as GraphTraceEvent, b5 as KnowledgeResolver, b6 as LiveTextConversation, b7 as LiveTurnResult, b8 as PlaybookLibraryEntry, b9 as PlaybookResolver, ba as RegistryToolsResolver, bb as RunLiveTextOptions, ag as RunTextSessionOptions, ah as RunTextTranscriptOptions, ay as TextSession, az as TextTranscriptResult, n as ToolExecutor, bc as dedupeConversationEmails, bd as denyPrivateNetwork, be as privateNetworkOptInHonoured, bf as runLiveTextConversation, aZ as runTextSession, a_ as runTextTranscript, bg as runWithOpenAIScope, bh as toPlaybookResolution } from '../text-session-
|
|
1
|
+
export { b1 as EmailResolver, b2 as FlowResolver, b3 as GraphResolvers, b4 as GraphTraceEvent, b5 as KnowledgeResolver, b6 as LiveTextConversation, b7 as LiveTurnResult, b8 as PlaybookLibraryEntry, b9 as PlaybookResolver, ba as RegistryToolsResolver, bb as RunLiveTextOptions, ag as RunTextSessionOptions, ah as RunTextTranscriptOptions, ay as TextSession, az as TextTranscriptResult, n as ToolExecutor, bc as dedupeConversationEmails, bd as denyPrivateNetwork, be as privateNetworkOptInHonoured, bf as runLiveTextConversation, aZ as runTextSession, a_ as runTextTranscript, bg as runWithOpenAIScope, bh as toPlaybookResolution } from '../text-session-B928dhkB.js';
|
|
2
2
|
import '@livekit/agents';
|
|
3
3
|
import 'zod';
|
|
4
4
|
import '../types-KqrAfY85.js';
|
|
@@ -14,6 +14,7 @@ import '@opentelemetry/sdk-logs';
|
|
|
14
14
|
import '@opentelemetry/sdk-metrics';
|
|
15
15
|
import '@opentelemetry/sdk-node';
|
|
16
16
|
import '@opentelemetry/semantic-conventions';
|
|
17
|
+
import { llm, DEFAULT_API_CONNECT_OPTIONS, intervalForRetry, APIStatusError, APITimeoutError, APIConnectionError } from '@livekit/agents';
|
|
17
18
|
import http from 'http';
|
|
18
19
|
import https from 'https';
|
|
19
20
|
import { Readable } from 'stream';
|
|
@@ -4076,32 +4077,116 @@ function acceptsReasoningEffort(model2) {
|
|
|
4076
4077
|
const id = baseModelId(model2);
|
|
4077
4078
|
return isReasoningModel(model2) && !/^o1-(mini|preview)/.test(id) && !/-chat(-|$)/.test(id);
|
|
4078
4079
|
}
|
|
4080
|
+
function acceptsNoReasoningEffort(model2) {
|
|
4081
|
+
if (!acceptsReasoningEffort(model2))
|
|
4082
|
+
return false;
|
|
4083
|
+
const id = baseModelId(model2);
|
|
4084
|
+
if (/-pro\b/.test(id))
|
|
4085
|
+
return false;
|
|
4086
|
+
const gpt = /^gpt-(\d+)(?:\.(\d+))?/.exec(id);
|
|
4087
|
+
if (!gpt)
|
|
4088
|
+
return false;
|
|
4089
|
+
const major = Number(gpt[1]);
|
|
4090
|
+
const minor = gpt[2] !== void 0 ? Number(gpt[2]) : 0;
|
|
4091
|
+
return major > 5 || major === 5 && minor >= 1;
|
|
4092
|
+
}
|
|
4093
|
+
function forgetLearnedReasoningEfforts() {
|
|
4094
|
+
learnedEfforts.clear();
|
|
4095
|
+
}
|
|
4096
|
+
function chatReasoningEffort(model2, opts) {
|
|
4097
|
+
const learned = learnedEfforts.get(learnedKey(model2, opts.tools === true));
|
|
4098
|
+
if (learned !== void 0)
|
|
4099
|
+
return learned === "omit" ? void 0 : learned;
|
|
4100
|
+
if (!acceptsReasoningEffort(model2))
|
|
4101
|
+
return void 0;
|
|
4102
|
+
if (opts.tools === true && acceptsNoReasoningEffort(model2))
|
|
4103
|
+
return "none";
|
|
4104
|
+
return opts.requested;
|
|
4105
|
+
}
|
|
4079
4106
|
function chatCompletionParams(model2, input) {
|
|
4107
|
+
const effort = chatReasoningEffort(model2, {
|
|
4108
|
+
...input.tools !== void 0 ? { tools: input.tools } : {},
|
|
4109
|
+
...input.reasoningEffort !== void 0 ? { requested: input.reasoningEffort } : {}
|
|
4110
|
+
});
|
|
4080
4111
|
if (isReasoningModel(model2)) {
|
|
4081
4112
|
return {
|
|
4082
4113
|
...input.maxTokens !== void 0 ? { max_completion_tokens: Math.max(input.maxTokens, REASONING_MIN_COMPLETION_TOKENS) } : {},
|
|
4083
|
-
...
|
|
4114
|
+
...effort !== void 0 ? { reasoning_effort: effort } : {}
|
|
4084
4115
|
};
|
|
4085
4116
|
}
|
|
4086
4117
|
return {
|
|
4118
|
+
// only when a provider taught the process that this model (one we don't know as a reasoning model) takes an effort
|
|
4119
|
+
...effort !== void 0 ? { reasoning_effort: effort } : {},
|
|
4087
4120
|
...input.maxTokens !== void 0 ? { max_tokens: input.maxTokens } : {},
|
|
4088
4121
|
...input.temperature !== void 0 ? { temperature: input.temperature } : {},
|
|
4089
4122
|
...input.topP !== void 0 ? { top_p: input.topP } : {}
|
|
4090
4123
|
};
|
|
4091
4124
|
}
|
|
4092
|
-
function
|
|
4125
|
+
function acceptsSamplingParams(model2) {
|
|
4126
|
+
return !isReasoningModel(model2);
|
|
4127
|
+
}
|
|
4128
|
+
function providerErrorOf(err) {
|
|
4129
|
+
if (err === null || typeof err !== "object")
|
|
4130
|
+
return null;
|
|
4093
4131
|
const e = err;
|
|
4094
|
-
const
|
|
4095
|
-
|
|
4132
|
+
const body = e["body"] !== null && typeof e["body"] === "object" ? e["body"] : {};
|
|
4133
|
+
const pick = (k) => e[k] !== void 0 && e[k] !== null ? e[k] : body[k];
|
|
4134
|
+
const statusRaw = typeof e["status"] === "number" ? e["status"] : e["statusCode"];
|
|
4135
|
+
const status = typeof statusRaw === "number" && statusRaw > 0 ? statusRaw : null;
|
|
4136
|
+
const code = pick("code");
|
|
4137
|
+
const type = pick("type");
|
|
4138
|
+
const param = pick("param");
|
|
4139
|
+
const message = typeof body["message"] === "string" ? body["message"] : typeof e["message"] === "string" ? e["message"] : "";
|
|
4140
|
+
return {
|
|
4141
|
+
status,
|
|
4142
|
+
code: typeof code === "string" ? code : typeof type === "string" ? type : "",
|
|
4143
|
+
param: typeof param === "string" ? param : null,
|
|
4144
|
+
message
|
|
4145
|
+
};
|
|
4146
|
+
}
|
|
4147
|
+
function reasoningEffortRejectionOf(err) {
|
|
4148
|
+
const f = providerErrorOf(err);
|
|
4149
|
+
if (!f || f.status !== 400)
|
|
4096
4150
|
return null;
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4151
|
+
if (f.param !== "reasoning_effort" && !/reasoning[_ ]effort/i.test(f.message))
|
|
4152
|
+
return null;
|
|
4153
|
+
return { status: f.status, message: f.message, suggestsNone: /reasoning[_ ]effort[^.]*\bnone\b/i.test(f.message) };
|
|
4154
|
+
}
|
|
4155
|
+
function learnReasoningEffort(model2, shape, err) {
|
|
4156
|
+
const rejection = reasoningEffortRejectionOf(err);
|
|
4157
|
+
if (!rejection)
|
|
4158
|
+
return false;
|
|
4159
|
+
const next = shape.sent !== "none" && (rejection.suggestsNone || shape.sent === void 0) ? "none" : "omit";
|
|
4160
|
+
if ((next === "omit" ? void 0 : next) === shape.sent)
|
|
4161
|
+
return false;
|
|
4162
|
+
learnedEfforts.set(learnedKey(model2, shape.tools), next);
|
|
4163
|
+
return true;
|
|
4164
|
+
}
|
|
4165
|
+
async function withReasoningEffortRetry(shape, call) {
|
|
4166
|
+
const sent = chatReasoningEffort(shape.model, {
|
|
4167
|
+
tools: shape.tools,
|
|
4168
|
+
...shape.requested !== void 0 ? { requested: shape.requested } : {}
|
|
4169
|
+
});
|
|
4170
|
+
try {
|
|
4171
|
+
return await call();
|
|
4172
|
+
} catch (err) {
|
|
4173
|
+
if (!learnReasoningEffort(shape.model, { tools: shape.tools, sent }, err))
|
|
4174
|
+
throw err;
|
|
4175
|
+
return call();
|
|
4176
|
+
}
|
|
4177
|
+
}
|
|
4178
|
+
function modelRejectionOf(err) {
|
|
4179
|
+
const f = providerErrorOf(err);
|
|
4180
|
+
const status = f?.status ?? null;
|
|
4181
|
+
if (!f || status === null || status !== 400 && status !== 403 && status !== 404)
|
|
4182
|
+
return null;
|
|
4183
|
+
const { code, param } = f;
|
|
4184
|
+
const rejected = REJECTION_CODES.has(code) || param !== null && MODEL_PARAMS.has(param) || reasoningEffortRejectionOf(err) !== null;
|
|
4100
4185
|
if (!rejected)
|
|
4101
4186
|
return null;
|
|
4102
4187
|
if (status === 403 && code !== "model_not_found")
|
|
4103
4188
|
return null;
|
|
4104
|
-
return { status, code: code || "invalid_request_error", message:
|
|
4189
|
+
return { status, code: code || "invalid_request_error", message: f.message };
|
|
4105
4190
|
}
|
|
4106
4191
|
async function withModelFallback(opts) {
|
|
4107
4192
|
const fallbackModel = opts.fallbackModel ?? PLATFORM_DEFAULT_CHAT_MODEL;
|
|
@@ -4122,11 +4207,13 @@ async function withModelFallback(opts) {
|
|
|
4122
4207
|
return opts.call(fallbackModel);
|
|
4123
4208
|
}
|
|
4124
4209
|
}
|
|
4125
|
-
var PLATFORM_DEFAULT_CHAT_MODEL, REASONING_MIN_COMPLETION_TOKENS, REJECTION_CODES, MODEL_PARAMS, MODEL_REJECTION_TTL_MS, ModelRejectionCache;
|
|
4210
|
+
var PLATFORM_DEFAULT_CHAT_MODEL, REASONING_MIN_COMPLETION_TOKENS, learnedEfforts, learnedKey, REJECTION_CODES, MODEL_PARAMS, MODEL_REJECTION_TTL_MS, ModelRejectionCache;
|
|
4126
4211
|
var init_chat_params = __esm({
|
|
4127
4212
|
"../llm-client/dist/chat-params.js"() {
|
|
4128
4213
|
PLATFORM_DEFAULT_CHAT_MODEL = "gpt-4o-mini";
|
|
4129
4214
|
REASONING_MIN_COMPLETION_TOKENS = 2048;
|
|
4215
|
+
learnedEfforts = /* @__PURE__ */ new Map();
|
|
4216
|
+
learnedKey = (model2, tools) => `${baseModelId(model2)}|${tools ? "tools" : "plain"}`;
|
|
4130
4217
|
REJECTION_CODES = /* @__PURE__ */ new Set(["unsupported_parameter", "unsupported_value", "model_not_found"]);
|
|
4131
4218
|
MODEL_PARAMS = /* @__PURE__ */ new Set(["model", "max_tokens", "max_completion_tokens", "temperature", "top_p", "reasoning_effort"]);
|
|
4132
4219
|
MODEL_REJECTION_TTL_MS = 5 * 60 * 1e3;
|
|
@@ -4154,6 +4241,30 @@ var init_chat_params = __esm({
|
|
|
4154
4241
|
};
|
|
4155
4242
|
}
|
|
4156
4243
|
});
|
|
4244
|
+
|
|
4245
|
+
// ../llm-client/dist/index.js
|
|
4246
|
+
var dist_exports = {};
|
|
4247
|
+
__export(dist_exports, {
|
|
4248
|
+
MODEL_REJECTION_TTL_MS: () => MODEL_REJECTION_TTL_MS,
|
|
4249
|
+
ModelRejectionCache: () => ModelRejectionCache,
|
|
4250
|
+
PLATFORM_DEFAULT_CHAT_MODEL: () => PLATFORM_DEFAULT_CHAT_MODEL,
|
|
4251
|
+
REASONING_MIN_COMPLETION_TOKENS: () => REASONING_MIN_COMPLETION_TOKENS,
|
|
4252
|
+
acceptsNoReasoningEffort: () => acceptsNoReasoningEffort,
|
|
4253
|
+
acceptsReasoningEffort: () => acceptsReasoningEffort,
|
|
4254
|
+
acceptsSamplingParams: () => acceptsSamplingParams,
|
|
4255
|
+
chatCompletionParams: () => chatCompletionParams,
|
|
4256
|
+
chatReasoningEffort: () => chatReasoningEffort,
|
|
4257
|
+
createChatClient: () => createChatClient,
|
|
4258
|
+
forgetLearnedReasoningEfforts: () => forgetLearnedReasoningEfforts,
|
|
4259
|
+
hasChatKey: () => hasChatKey,
|
|
4260
|
+
isReasoningModel: () => isReasoningModel,
|
|
4261
|
+
learnReasoningEffort: () => learnReasoningEffort,
|
|
4262
|
+
modelRejectionOf: () => modelRejectionOf,
|
|
4263
|
+
providerErrorOf: () => providerErrorOf,
|
|
4264
|
+
reasoningEffortRejectionOf: () => reasoningEffortRejectionOf,
|
|
4265
|
+
withModelFallback: () => withModelFallback,
|
|
4266
|
+
withReasoningEffortRetry: () => withReasoningEffortRetry
|
|
4267
|
+
});
|
|
4157
4268
|
function createChatClient(config = {}) {
|
|
4158
4269
|
return new OpenAI({
|
|
4159
4270
|
...config.apiKey ? { apiKey: config.apiKey } : {},
|
|
@@ -4161,6 +4272,9 @@ function createChatClient(config = {}) {
|
|
|
4161
4272
|
...config.timeoutMs ? { timeout: config.timeoutMs } : {}
|
|
4162
4273
|
});
|
|
4163
4274
|
}
|
|
4275
|
+
function hasChatKey(config = {}) {
|
|
4276
|
+
return Boolean(config.apiKey || process.env["OPENAI_API_KEY"]);
|
|
4277
|
+
}
|
|
4164
4278
|
var init_dist = __esm({
|
|
4165
4279
|
"../llm-client/dist/index.js"() {
|
|
4166
4280
|
init_chat_params();
|
|
@@ -4300,6 +4414,340 @@ var init_wrap = __esm({
|
|
|
4300
4414
|
"src/providers/wrap.ts"() {
|
|
4301
4415
|
}
|
|
4302
4416
|
});
|
|
4417
|
+
var init_start = __esm({
|
|
4418
|
+
"../observability/dist/start.js"() {
|
|
4419
|
+
}
|
|
4420
|
+
});
|
|
4421
|
+
|
|
4422
|
+
// ../observability/dist/attributes.js
|
|
4423
|
+
var ATTR;
|
|
4424
|
+
var init_attributes = __esm({
|
|
4425
|
+
"../observability/dist/attributes.js"() {
|
|
4426
|
+
ATTR = {
|
|
4427
|
+
projectId: "vl.project_id",
|
|
4428
|
+
callId: "vl.call_id",
|
|
4429
|
+
campaignId: "vl.campaign_id",
|
|
4430
|
+
room: "vl.room",
|
|
4431
|
+
agentId: "vl.agent_id",
|
|
4432
|
+
phoneNumberId: "vl.phone_number_id",
|
|
4433
|
+
bindingId: "vl.binding_id",
|
|
4434
|
+
source: "vl.source",
|
|
4435
|
+
kind: "vl.kind"
|
|
4436
|
+
};
|
|
4437
|
+
}
|
|
4438
|
+
});
|
|
4439
|
+
function getCurrentCallContext() {
|
|
4440
|
+
return callContextStore.getStore();
|
|
4441
|
+
}
|
|
4442
|
+
var callContextStore;
|
|
4443
|
+
var init_call_context = __esm({
|
|
4444
|
+
"../observability/dist/call-context.js"() {
|
|
4445
|
+
init_attributes();
|
|
4446
|
+
callContextStore = new AsyncLocalStorage();
|
|
4447
|
+
}
|
|
4448
|
+
});
|
|
4449
|
+
var init_trace_propagation = __esm({
|
|
4450
|
+
"../observability/dist/trace-propagation.js"() {
|
|
4451
|
+
}
|
|
4452
|
+
});
|
|
4453
|
+
function meter() {
|
|
4454
|
+
return metrics.getMeter(METER_NAME, METER_VERSION);
|
|
4455
|
+
}
|
|
4456
|
+
function modelFallbacks() {
|
|
4457
|
+
return _modelFallbacks ??= meter().createCounter("vl.llm.model_fallback", {
|
|
4458
|
+
description: "Model calls the provider rejected that fell back to the platform default model",
|
|
4459
|
+
unit: "{fallbacks}"
|
|
4460
|
+
});
|
|
4461
|
+
}
|
|
4462
|
+
function recordModelFallback(args) {
|
|
4463
|
+
const out = {
|
|
4464
|
+
"vl.model": args.model,
|
|
4465
|
+
"vl.fallback_model": args.fallbackModel,
|
|
4466
|
+
"vl.error_code": args.code
|
|
4467
|
+
};
|
|
4468
|
+
if (args.projectId)
|
|
4469
|
+
out[ATTR.projectId] = args.projectId;
|
|
4470
|
+
if (args.agentId)
|
|
4471
|
+
out[ATTR.agentId] = args.agentId;
|
|
4472
|
+
if (args.surface)
|
|
4473
|
+
out["vl.surface"] = args.surface;
|
|
4474
|
+
modelFallbacks().add(1, out);
|
|
4475
|
+
}
|
|
4476
|
+
var METER_NAME, METER_VERSION, _modelFallbacks;
|
|
4477
|
+
var init_metrics = __esm({
|
|
4478
|
+
"../observability/dist/metrics.js"() {
|
|
4479
|
+
init_attributes();
|
|
4480
|
+
METER_NAME = "voicelayer";
|
|
4481
|
+
METER_VERSION = "0.1.0";
|
|
4482
|
+
_modelFallbacks = null;
|
|
4483
|
+
}
|
|
4484
|
+
});
|
|
4485
|
+
var init_latency_span = __esm({
|
|
4486
|
+
"../observability/dist/latency-span.js"() {
|
|
4487
|
+
init_attributes();
|
|
4488
|
+
}
|
|
4489
|
+
});
|
|
4490
|
+
|
|
4491
|
+
// ../observability/dist/index.js
|
|
4492
|
+
var init_dist2 = __esm({
|
|
4493
|
+
"../observability/dist/index.js"() {
|
|
4494
|
+
init_start();
|
|
4495
|
+
init_call_context();
|
|
4496
|
+
init_trace_propagation();
|
|
4497
|
+
init_attributes();
|
|
4498
|
+
init_metrics();
|
|
4499
|
+
init_latency_span();
|
|
4500
|
+
}
|
|
4501
|
+
});
|
|
4502
|
+
|
|
4503
|
+
// src/providers/resilient-llm.ts
|
|
4504
|
+
var resilient_llm_exports = {};
|
|
4505
|
+
__export(resilient_llm_exports, {
|
|
4506
|
+
LLM_APOLOGY: () => LLM_APOLOGY,
|
|
4507
|
+
ResilientLLM: () => ResilientLLM,
|
|
4508
|
+
isResilientLLM: () => isResilientLLM
|
|
4509
|
+
});
|
|
4510
|
+
function isResilientLLM(value) {
|
|
4511
|
+
return typeof value === "object" && value !== null && value[RESILIENT] === true;
|
|
4512
|
+
}
|
|
4513
|
+
function transient(error) {
|
|
4514
|
+
if (error instanceof APIStatusError) {
|
|
4515
|
+
const s = error.statusCode;
|
|
4516
|
+
return s === 408 || s === 429 || s < 0 || s >= 500;
|
|
4517
|
+
}
|
|
4518
|
+
return error instanceof APITimeoutError || error instanceof APIConnectionError;
|
|
4519
|
+
}
|
|
4520
|
+
var LLM_APOLOGY, RESILIENT, ResilientLLM, sameModel, ServedLLM, ResilientLLMStream;
|
|
4521
|
+
var init_resilient_llm = __esm({
|
|
4522
|
+
"src/providers/resilient-llm.ts"() {
|
|
4523
|
+
init_dist();
|
|
4524
|
+
init_dist2();
|
|
4525
|
+
LLM_APOLOGY = "Sorry, I'm having trouble right now. Could you give me a moment and say that again?";
|
|
4526
|
+
RESILIENT = /* @__PURE__ */ Symbol.for("voicelayer.resilientLLM");
|
|
4527
|
+
ResilientLLM = class extends llm.LLM {
|
|
4528
|
+
[RESILIENT] = true;
|
|
4529
|
+
#opts;
|
|
4530
|
+
#fallback = null;
|
|
4531
|
+
#listeners = /* @__PURE__ */ new Set();
|
|
4532
|
+
/** Models the provider rejected on this call (a call's pipeline is built per call): later turns go straight to the fallback. */
|
|
4533
|
+
rejections = new ModelRejectionCache();
|
|
4534
|
+
constructor(opts) {
|
|
4535
|
+
super();
|
|
4536
|
+
this.#opts = opts;
|
|
4537
|
+
}
|
|
4538
|
+
label() {
|
|
4539
|
+
return this.#opts.primary.label();
|
|
4540
|
+
}
|
|
4541
|
+
get model() {
|
|
4542
|
+
return this.#opts.primary.model;
|
|
4543
|
+
}
|
|
4544
|
+
get provider() {
|
|
4545
|
+
return this.#opts.primary.provider;
|
|
4546
|
+
}
|
|
4547
|
+
get apology() {
|
|
4548
|
+
return this.#opts.apology ?? LLM_APOLOGY;
|
|
4549
|
+
}
|
|
4550
|
+
get reasoningParams() {
|
|
4551
|
+
return this.#opts.reasoningParams === true;
|
|
4552
|
+
}
|
|
4553
|
+
/** The fallback LLM, built on first need; null when there is none or it is the agent's own model. */
|
|
4554
|
+
fallbackLLM() {
|
|
4555
|
+
if (!this.#opts.fallback) return null;
|
|
4556
|
+
this.#fallback ??= this.#opts.fallback();
|
|
4557
|
+
return sameModel(this.#fallback.model, this.model) ? null : this.#fallback;
|
|
4558
|
+
}
|
|
4559
|
+
/** Hear about every recovery (and every apology). Returns the unsubscribe. */
|
|
4560
|
+
onIncident(listener) {
|
|
4561
|
+
this.#listeners.add(listener);
|
|
4562
|
+
return () => this.#listeners.delete(listener);
|
|
4563
|
+
}
|
|
4564
|
+
/** @internal */
|
|
4565
|
+
report(incident) {
|
|
4566
|
+
const log = incident.kind === "apology" ? console.error : console.warn;
|
|
4567
|
+
log(`[voicelayer] llm ${incident.kind.replace(/_/g, " ")}`, incident);
|
|
4568
|
+
if (incident.kind === "model_fallback") {
|
|
4569
|
+
const call = getCurrentCallContext();
|
|
4570
|
+
recordModelFallback({
|
|
4571
|
+
model: incident.model,
|
|
4572
|
+
fallbackModel: incident.fallbackModel,
|
|
4573
|
+
code: incident.code,
|
|
4574
|
+
surface: "voice",
|
|
4575
|
+
...call?.projectId ? { projectId: call.projectId } : {},
|
|
4576
|
+
...call?.agentId ? { agentId: call.agentId } : {}
|
|
4577
|
+
});
|
|
4578
|
+
}
|
|
4579
|
+
for (const listener of this.#listeners) {
|
|
4580
|
+
try {
|
|
4581
|
+
listener(incident);
|
|
4582
|
+
} catch {
|
|
4583
|
+
}
|
|
4584
|
+
}
|
|
4585
|
+
}
|
|
4586
|
+
chat(args) {
|
|
4587
|
+
return new ResilientLLMStream(this, args);
|
|
4588
|
+
}
|
|
4589
|
+
prewarm() {
|
|
4590
|
+
this.#opts.primary.prewarm();
|
|
4591
|
+
}
|
|
4592
|
+
async aclose() {
|
|
4593
|
+
await Promise.all([this.#opts.primary.aclose(), this.#fallback?.aclose()]);
|
|
4594
|
+
}
|
|
4595
|
+
/** @internal */
|
|
4596
|
+
get primary() {
|
|
4597
|
+
return this.#opts.primary;
|
|
4598
|
+
}
|
|
4599
|
+
};
|
|
4600
|
+
sameModel = (a, b) => a.trim().toLowerCase() === b.trim().toLowerCase();
|
|
4601
|
+
ServedLLM = class extends llm.LLM {
|
|
4602
|
+
constructor(owner, served) {
|
|
4603
|
+
super();
|
|
4604
|
+
this.owner = owner;
|
|
4605
|
+
this.served = served;
|
|
4606
|
+
}
|
|
4607
|
+
owner;
|
|
4608
|
+
served;
|
|
4609
|
+
label() {
|
|
4610
|
+
return this.owner.label();
|
|
4611
|
+
}
|
|
4612
|
+
get model() {
|
|
4613
|
+
return this.served();
|
|
4614
|
+
}
|
|
4615
|
+
get provider() {
|
|
4616
|
+
return this.owner.provider;
|
|
4617
|
+
}
|
|
4618
|
+
chat(args) {
|
|
4619
|
+
return this.owner.chat(args);
|
|
4620
|
+
}
|
|
4621
|
+
emit(event, ...args) {
|
|
4622
|
+
return this.owner.emit(event, ...args);
|
|
4623
|
+
}
|
|
4624
|
+
};
|
|
4625
|
+
ResilientLLMStream = class extends llm.LLMStream {
|
|
4626
|
+
#owner;
|
|
4627
|
+
#args;
|
|
4628
|
+
#conn;
|
|
4629
|
+
/** The model answering this stream — what its metrics report. */
|
|
4630
|
+
#served;
|
|
4631
|
+
#current = null;
|
|
4632
|
+
constructor(owner, args) {
|
|
4633
|
+
const conn = args.connOptions ?? DEFAULT_API_CONNECT_OPTIONS;
|
|
4634
|
+
const served = { model: owner.model };
|
|
4635
|
+
super(new ServedLLM(owner, () => served.model), {
|
|
4636
|
+
chatCtx: args.chatCtx,
|
|
4637
|
+
...args.toolCtx ? { toolCtx: args.toolCtx } : {},
|
|
4638
|
+
connOptions: { ...conn, maxRetry: 0 }
|
|
4639
|
+
});
|
|
4640
|
+
this.#owner = owner;
|
|
4641
|
+
this.#args = args;
|
|
4642
|
+
this.#conn = conn;
|
|
4643
|
+
this.#served = served;
|
|
4644
|
+
this.abortController.signal.addEventListener("abort", () => this.#current?.close());
|
|
4645
|
+
}
|
|
4646
|
+
get #hasTools() {
|
|
4647
|
+
return this.#args.toolCtx !== void 0 && Object.keys(this.#args.toolCtx).length > 0;
|
|
4648
|
+
}
|
|
4649
|
+
#extraKwargs(model2) {
|
|
4650
|
+
const base = this.#args.extraKwargs;
|
|
4651
|
+
if (!this.#owner.reasoningParams) return base;
|
|
4652
|
+
const effort = chatReasoningEffort(model2, { tools: this.#hasTools });
|
|
4653
|
+
if (effort === void 0) {
|
|
4654
|
+
if (!base || !("reasoning_effort" in base)) return base;
|
|
4655
|
+
const { reasoning_effort: _dropped, ...rest } = base;
|
|
4656
|
+
return rest;
|
|
4657
|
+
}
|
|
4658
|
+
return { ...base, reasoning_effort: effort };
|
|
4659
|
+
}
|
|
4660
|
+
/** One request on `target`, forwarding its chunks. Its failure is the inner LLM's 'error' event. */
|
|
4661
|
+
async #attempt(target) {
|
|
4662
|
+
let failure = null;
|
|
4663
|
+
const onError = (ev) => {
|
|
4664
|
+
failure ??= ev.error;
|
|
4665
|
+
};
|
|
4666
|
+
target.on("error", onError);
|
|
4667
|
+
let started = false;
|
|
4668
|
+
try {
|
|
4669
|
+
const extraKwargs = this.#extraKwargs(target.model);
|
|
4670
|
+
const stream = target.chat({
|
|
4671
|
+
...this.#args,
|
|
4672
|
+
connOptions: { ...this.#conn, maxRetry: 0 },
|
|
4673
|
+
...extraKwargs !== void 0 ? { extraKwargs } : {}
|
|
4674
|
+
});
|
|
4675
|
+
this.#current = stream;
|
|
4676
|
+
for await (const chunk of stream) {
|
|
4677
|
+
if (this.abortController.signal.aborted) break;
|
|
4678
|
+
started = true;
|
|
4679
|
+
this.queue.put(chunk);
|
|
4680
|
+
}
|
|
4681
|
+
} catch (err) {
|
|
4682
|
+
failure ??= err instanceof Error ? err : new Error(String(err));
|
|
4683
|
+
} finally {
|
|
4684
|
+
target.off("error", onError);
|
|
4685
|
+
this.#current = null;
|
|
4686
|
+
}
|
|
4687
|
+
return failure ? { ok: false, error: failure, started } : { ok: true };
|
|
4688
|
+
}
|
|
4689
|
+
/** Run `target` until it answers, or a failure that retrying it won't fix. */
|
|
4690
|
+
async #run(target) {
|
|
4691
|
+
let effortRetried = false;
|
|
4692
|
+
for (let retries = 0; ; ) {
|
|
4693
|
+
const sent = this.#owner.reasoningParams ? chatReasoningEffort(target.model, { tools: this.#hasTools }) : void 0;
|
|
4694
|
+
const result = await this.#attempt(target);
|
|
4695
|
+
if (result.ok || result.started || this.abortController.signal.aborted) return result;
|
|
4696
|
+
if (this.#owner.reasoningParams && !effortRetried && learnReasoningEffort(target.model, { tools: this.#hasTools, sent }, result.error)) {
|
|
4697
|
+
effortRetried = true;
|
|
4698
|
+
this.#owner.report({
|
|
4699
|
+
kind: "reasoning_effort_adapted",
|
|
4700
|
+
model: target.model,
|
|
4701
|
+
message: providerErrorOf(result.error)?.message ?? result.error.message
|
|
4702
|
+
});
|
|
4703
|
+
continue;
|
|
4704
|
+
}
|
|
4705
|
+
if (!transient(result.error) || retries >= this.#conn.maxRetry) return result;
|
|
4706
|
+
const wait = intervalForRetry(this.#conn, retries);
|
|
4707
|
+
retries += 1;
|
|
4708
|
+
if (wait > 0) await new Promise((r) => setTimeout(r, wait));
|
|
4709
|
+
if (this.abortController.signal.aborted) return result;
|
|
4710
|
+
}
|
|
4711
|
+
}
|
|
4712
|
+
async run() {
|
|
4713
|
+
const owner = this.#owner;
|
|
4714
|
+
const model2 = owner.model;
|
|
4715
|
+
const fallback = owner.fallbackLLM();
|
|
4716
|
+
const known = fallback ? owner.rejections.get(model2) : null;
|
|
4717
|
+
let failure;
|
|
4718
|
+
if (known && fallback) {
|
|
4719
|
+
owner.report({ kind: "model_fallback", model: model2, fallbackModel: fallback.model, code: known.code, message: known.message, cached: true });
|
|
4720
|
+
failure = new Error(known.message);
|
|
4721
|
+
} else {
|
|
4722
|
+
const first = await this.#run(owner.primary);
|
|
4723
|
+
if (first.ok || first.started || this.abortController.signal.aborted) return;
|
|
4724
|
+
failure = first.error;
|
|
4725
|
+
const rejection = modelRejectionOf(first.error);
|
|
4726
|
+
if (rejection) owner.rejections.set(model2, rejection);
|
|
4727
|
+
if (fallback) {
|
|
4728
|
+
const f = providerErrorOf(first.error);
|
|
4729
|
+
owner.report({
|
|
4730
|
+
kind: "model_fallback",
|
|
4731
|
+
model: model2,
|
|
4732
|
+
fallbackModel: fallback.model,
|
|
4733
|
+
code: rejection?.code ?? (f?.status ? String(f.status) : "error"),
|
|
4734
|
+
message: f?.message || first.error.message,
|
|
4735
|
+
cached: false
|
|
4736
|
+
});
|
|
4737
|
+
}
|
|
4738
|
+
}
|
|
4739
|
+
if (fallback) {
|
|
4740
|
+
this.#served.model = fallback.model;
|
|
4741
|
+
const second = await this.#run(fallback);
|
|
4742
|
+
if (second.ok || second.started || this.abortController.signal.aborted) return;
|
|
4743
|
+
failure = second.error;
|
|
4744
|
+
}
|
|
4745
|
+
owner.report({ kind: "apology", model: this.#served.model, message: providerErrorOf(failure)?.message || failure.message });
|
|
4746
|
+
this.queue.put({ id: `vl-apology-${Date.now()}`, delta: { role: "assistant", content: owner.apology } });
|
|
4747
|
+
}
|
|
4748
|
+
};
|
|
4749
|
+
}
|
|
4750
|
+
});
|
|
4303
4751
|
|
|
4304
4752
|
// src/providers/index.ts
|
|
4305
4753
|
async function importOptional(spec, hint) {
|
|
@@ -4346,9 +4794,13 @@ var init_providers2 = __esm({
|
|
|
4346
4794
|
llm(options = {}) {
|
|
4347
4795
|
return async () => {
|
|
4348
4796
|
const oa = await importOptional("@voicelayer/agents-plugin-openai", "openai.llm");
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4797
|
+
const { ResilientLLM: ResilientLLM2 } = await Promise.resolve().then(() => (init_resilient_llm(), resilient_llm_exports));
|
|
4798
|
+
const { PLATFORM_DEFAULT_CHAT_MODEL: PLATFORM_DEFAULT_CHAT_MODEL2 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
|
|
4799
|
+
return new ResilientLLM2({
|
|
4800
|
+
primary: new oa.LLM(withCreds({ model: options.model ?? "gpt-4o-mini" }, options)),
|
|
4801
|
+
fallback: () => new oa.LLM(withCreds({ model: PLATFORM_DEFAULT_CHAT_MODEL2 }, options)),
|
|
4802
|
+
reasoningParams: true
|
|
4803
|
+
});
|
|
4352
4804
|
};
|
|
4353
4805
|
},
|
|
4354
4806
|
tts(options = {}) {
|
|
@@ -4424,9 +4876,10 @@ var init_providers2 = __esm({
|
|
|
4424
4876
|
llm(options = {}) {
|
|
4425
4877
|
return async () => {
|
|
4426
4878
|
const g = await importOptional("@voicelayer/agents-plugin-google", "google.llm");
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4879
|
+
const { ResilientLLM: ResilientLLM2 } = await Promise.resolve().then(() => (init_resilient_llm(), resilient_llm_exports));
|
|
4880
|
+
return new ResilientLLM2({
|
|
4881
|
+
primary: new g.LLM(withCreds({ model: options.model ?? "gemini-3.8-flash" }, options))
|
|
4882
|
+
});
|
|
4430
4883
|
};
|
|
4431
4884
|
},
|
|
4432
4885
|
realtime(options = {}) {
|
|
@@ -4528,91 +4981,6 @@ var init_llm = __esm({
|
|
|
4528
4981
|
init_registry();
|
|
4529
4982
|
}
|
|
4530
4983
|
});
|
|
4531
|
-
var init_start = __esm({
|
|
4532
|
-
"../observability/dist/start.js"() {
|
|
4533
|
-
}
|
|
4534
|
-
});
|
|
4535
|
-
|
|
4536
|
-
// ../observability/dist/attributes.js
|
|
4537
|
-
var ATTR;
|
|
4538
|
-
var init_attributes = __esm({
|
|
4539
|
-
"../observability/dist/attributes.js"() {
|
|
4540
|
-
ATTR = {
|
|
4541
|
-
projectId: "vl.project_id",
|
|
4542
|
-
callId: "vl.call_id",
|
|
4543
|
-
campaignId: "vl.campaign_id",
|
|
4544
|
-
room: "vl.room",
|
|
4545
|
-
agentId: "vl.agent_id",
|
|
4546
|
-
phoneNumberId: "vl.phone_number_id",
|
|
4547
|
-
bindingId: "vl.binding_id",
|
|
4548
|
-
source: "vl.source",
|
|
4549
|
-
kind: "vl.kind"
|
|
4550
|
-
};
|
|
4551
|
-
}
|
|
4552
|
-
});
|
|
4553
|
-
function getCurrentCallContext() {
|
|
4554
|
-
return callContextStore.getStore();
|
|
4555
|
-
}
|
|
4556
|
-
var callContextStore;
|
|
4557
|
-
var init_call_context = __esm({
|
|
4558
|
-
"../observability/dist/call-context.js"() {
|
|
4559
|
-
init_attributes();
|
|
4560
|
-
callContextStore = new AsyncLocalStorage();
|
|
4561
|
-
}
|
|
4562
|
-
});
|
|
4563
|
-
var init_trace_propagation = __esm({
|
|
4564
|
-
"../observability/dist/trace-propagation.js"() {
|
|
4565
|
-
}
|
|
4566
|
-
});
|
|
4567
|
-
function meter() {
|
|
4568
|
-
return metrics.getMeter(METER_NAME, METER_VERSION);
|
|
4569
|
-
}
|
|
4570
|
-
function modelFallbacks() {
|
|
4571
|
-
return _modelFallbacks ??= meter().createCounter("vl.llm.model_fallback", {
|
|
4572
|
-
description: "Model calls the provider rejected that fell back to the platform default model",
|
|
4573
|
-
unit: "{fallbacks}"
|
|
4574
|
-
});
|
|
4575
|
-
}
|
|
4576
|
-
function recordModelFallback(args) {
|
|
4577
|
-
const out = {
|
|
4578
|
-
"vl.model": args.model,
|
|
4579
|
-
"vl.fallback_model": args.fallbackModel,
|
|
4580
|
-
"vl.error_code": args.code
|
|
4581
|
-
};
|
|
4582
|
-
if (args.projectId)
|
|
4583
|
-
out[ATTR.projectId] = args.projectId;
|
|
4584
|
-
if (args.agentId)
|
|
4585
|
-
out[ATTR.agentId] = args.agentId;
|
|
4586
|
-
if (args.surface)
|
|
4587
|
-
out["vl.surface"] = args.surface;
|
|
4588
|
-
modelFallbacks().add(1, out);
|
|
4589
|
-
}
|
|
4590
|
-
var METER_NAME, METER_VERSION, _modelFallbacks;
|
|
4591
|
-
var init_metrics = __esm({
|
|
4592
|
-
"../observability/dist/metrics.js"() {
|
|
4593
|
-
init_attributes();
|
|
4594
|
-
METER_NAME = "voicelayer";
|
|
4595
|
-
METER_VERSION = "0.1.0";
|
|
4596
|
-
_modelFallbacks = null;
|
|
4597
|
-
}
|
|
4598
|
-
});
|
|
4599
|
-
var init_latency_span = __esm({
|
|
4600
|
-
"../observability/dist/latency-span.js"() {
|
|
4601
|
-
init_attributes();
|
|
4602
|
-
}
|
|
4603
|
-
});
|
|
4604
|
-
|
|
4605
|
-
// ../observability/dist/index.js
|
|
4606
|
-
var init_dist2 = __esm({
|
|
4607
|
-
"../observability/dist/index.js"() {
|
|
4608
|
-
init_start();
|
|
4609
|
-
init_call_context();
|
|
4610
|
-
init_trace_propagation();
|
|
4611
|
-
init_attributes();
|
|
4612
|
-
init_metrics();
|
|
4613
|
-
init_latency_span();
|
|
4614
|
-
}
|
|
4615
|
-
});
|
|
4616
4984
|
|
|
4617
4985
|
// src/runtime/helper-models.ts
|
|
4618
4986
|
function rejectionsFor(client) {
|