@agenticmail/core 0.9.37 → 0.9.39
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/{chunk-J6JINNJ3.js → chunk-FYULLCZX.js} +10 -6
- package/dist/index.cjs +181 -7
- package/dist/index.d.cts +195 -1
- package/dist/index.d.ts +195 -1
- package/dist/index.js +169 -3
- package/dist/{skills-RE3S767B.js → skills-DZVDIMTD.js} +1 -1
- package/package.json +1 -1
|
@@ -575,8 +575,8 @@ function validateSkill(s) {
|
|
|
575
575
|
if (typeof sk.contributed_by !== "string") errs.push({ path: "contributed_by", message: "must be a string" });
|
|
576
576
|
return errs;
|
|
577
577
|
}
|
|
578
|
-
function summarize(s) {
|
|
579
|
-
|
|
578
|
+
function summarize(s, score) {
|
|
579
|
+
const out = {
|
|
580
580
|
id: s.id,
|
|
581
581
|
name: s.name,
|
|
582
582
|
category: s.category,
|
|
@@ -584,8 +584,12 @@ function summarize(s) {
|
|
|
584
584
|
description: s.description,
|
|
585
585
|
version: s.version,
|
|
586
586
|
disclaimer_required: !!s.disclaimer,
|
|
587
|
-
estimated_call_duration_minutes: s.context.estimated_call_duration_minutes
|
|
587
|
+
estimated_call_duration_minutes: s.context.estimated_call_duration_minutes,
|
|
588
|
+
when_to_use: s.context.when_to_use,
|
|
589
|
+
first_principle: s.principles && s.principles.length > 0 ? s.principles[0] : ""
|
|
588
590
|
};
|
|
591
|
+
if (score !== void 0) out.score = score;
|
|
592
|
+
return out;
|
|
589
593
|
}
|
|
590
594
|
function listSkills(opts = {}) {
|
|
591
595
|
const all = Array.from(ensureLoaded().byId.values());
|
|
@@ -606,17 +610,17 @@ function searchSkills(query, limit = 20) {
|
|
|
606
610
|
const fallback = [];
|
|
607
611
|
for (const s of byId.values()) {
|
|
608
612
|
if (s.id.toLowerCase().includes(qLow) || s.name.toLowerCase().includes(qLow) || s.tags.some((t) => t.toLowerCase().includes(qLow))) {
|
|
609
|
-
fallback.push(summarize(s));
|
|
613
|
+
fallback.push(summarize(s, 0.1));
|
|
610
614
|
if (fallback.length >= limit) break;
|
|
611
615
|
}
|
|
612
616
|
}
|
|
613
617
|
return fallback;
|
|
614
618
|
}
|
|
615
619
|
const out = [];
|
|
616
|
-
for (const { id } of ranked) {
|
|
620
|
+
for (const { id, score } of ranked) {
|
|
617
621
|
const skill = byId.get(id);
|
|
618
622
|
if (!skill) continue;
|
|
619
|
-
out.push(summarize(skill));
|
|
623
|
+
out.push(summarize(skill, score));
|
|
620
624
|
if (out.length >= limit) break;
|
|
621
625
|
}
|
|
622
626
|
return out;
|
package/dist/index.cjs
CHANGED
|
@@ -1280,8 +1280,8 @@ function validateSkill(s) {
|
|
|
1280
1280
|
if (typeof sk.contributed_by !== "string") errs.push({ path: "contributed_by", message: "must be a string" });
|
|
1281
1281
|
return errs;
|
|
1282
1282
|
}
|
|
1283
|
-
function summarize(s) {
|
|
1284
|
-
|
|
1283
|
+
function summarize(s, score) {
|
|
1284
|
+
const out = {
|
|
1285
1285
|
id: s.id,
|
|
1286
1286
|
name: s.name,
|
|
1287
1287
|
category: s.category,
|
|
@@ -1289,8 +1289,12 @@ function summarize(s) {
|
|
|
1289
1289
|
description: s.description,
|
|
1290
1290
|
version: s.version,
|
|
1291
1291
|
disclaimer_required: !!s.disclaimer,
|
|
1292
|
-
estimated_call_duration_minutes: s.context.estimated_call_duration_minutes
|
|
1292
|
+
estimated_call_duration_minutes: s.context.estimated_call_duration_minutes,
|
|
1293
|
+
when_to_use: s.context.when_to_use,
|
|
1294
|
+
first_principle: s.principles && s.principles.length > 0 ? s.principles[0] : ""
|
|
1293
1295
|
};
|
|
1296
|
+
if (score !== void 0) out.score = score;
|
|
1297
|
+
return out;
|
|
1294
1298
|
}
|
|
1295
1299
|
function listSkills(opts = {}) {
|
|
1296
1300
|
const all = Array.from(ensureLoaded().byId.values());
|
|
@@ -1311,17 +1315,17 @@ function searchSkills(query, limit = 20) {
|
|
|
1311
1315
|
const fallback = [];
|
|
1312
1316
|
for (const s of byId.values()) {
|
|
1313
1317
|
if (s.id.toLowerCase().includes(qLow) || s.name.toLowerCase().includes(qLow) || s.tags.some((t) => t.toLowerCase().includes(qLow))) {
|
|
1314
|
-
fallback.push(summarize(s));
|
|
1318
|
+
fallback.push(summarize(s, 0.1));
|
|
1315
1319
|
if (fallback.length >= limit) break;
|
|
1316
1320
|
}
|
|
1317
1321
|
}
|
|
1318
1322
|
return fallback;
|
|
1319
1323
|
}
|
|
1320
1324
|
const out = [];
|
|
1321
|
-
for (const { id } of ranked) {
|
|
1325
|
+
for (const { id, score } of ranked) {
|
|
1322
1326
|
const skill = byId.get(id);
|
|
1323
1327
|
if (!skill) continue;
|
|
1324
|
-
out.push(summarize(skill));
|
|
1328
|
+
out.push(summarize(skill, score));
|
|
1325
1329
|
if (out.length >= limit) break;
|
|
1326
1330
|
}
|
|
1327
1331
|
return out;
|
|
@@ -1606,6 +1610,7 @@ __export(index_exports, {
|
|
|
1606
1610
|
getTelegramMe: () => getTelegramMe,
|
|
1607
1611
|
getTelegramUpdates: () => getTelegramUpdates,
|
|
1608
1612
|
getTelegramWebhookInfo: () => getTelegramWebhookInfo,
|
|
1613
|
+
getVoiceProvider: () => getVoiceProvider,
|
|
1609
1614
|
hostSessionStoragePath: () => hostSessionStoragePath,
|
|
1610
1615
|
inferPhoneRegion: () => inferPhoneRegion,
|
|
1611
1616
|
invalidateSkillCache: () => invalidateSkillCache,
|
|
@@ -1618,6 +1623,7 @@ __export(index_exports, {
|
|
|
1618
1623
|
isTelegramStopCommand: () => isTelegramStopCommand,
|
|
1619
1624
|
isValidPhoneNumber: () => isValidPhoneNumber,
|
|
1620
1625
|
listSkills: () => listSkills,
|
|
1626
|
+
listVoiceProviders: () => listVoiceProviders,
|
|
1621
1627
|
loadAgentPersona: () => loadAgentPersona,
|
|
1622
1628
|
loadHostSession: () => loadHostSession,
|
|
1623
1629
|
loadSkill: () => loadSkill,
|
|
@@ -1646,6 +1652,7 @@ __export(index_exports, {
|
|
|
1646
1652
|
redactSecret: () => redactSecret,
|
|
1647
1653
|
redactSmsConfig: () => redactSmsConfig,
|
|
1648
1654
|
redactTelegramConfig: () => redactTelegramConfig,
|
|
1655
|
+
registerVoiceProvider: () => registerVoiceProvider,
|
|
1649
1656
|
renderSkillAsPrompt: () => renderSkillAsPrompt,
|
|
1650
1657
|
requireBinary: () => requireBinary,
|
|
1651
1658
|
requireWhisperModel: () => requireWhisperModel,
|
|
@@ -1653,6 +1660,7 @@ __export(index_exports, {
|
|
|
1653
1660
|
resolveConfig: () => resolveConfig,
|
|
1654
1661
|
resolveExtensionPolicy: () => resolveExtensionPolicy,
|
|
1655
1662
|
resolveTlsRejectUnauthorized: () => resolveTlsRejectUnauthorized,
|
|
1663
|
+
resolveVoiceRuntime: () => resolveVoiceRuntime,
|
|
1656
1664
|
safeJoin: () => safeJoin,
|
|
1657
1665
|
sanitizeEmail: () => sanitizeEmail,
|
|
1658
1666
|
saveAgentPersona: () => saveAgentPersona,
|
|
@@ -2584,6 +2592,13 @@ function resolveConfig(overrides) {
|
|
|
2584
2592
|
dataDir: env.AGENTICMAIL_DATA_DIR?.replace(/^~(?=\/|$)/, (0, import_node_os.homedir)()) ?? DEFAULT_CONFIG.dataDir
|
|
2585
2593
|
};
|
|
2586
2594
|
if (env.OPENAI_API_KEY) config.openaiApiKey = env.OPENAI_API_KEY;
|
|
2595
|
+
if (env.XAI_API_KEY) {
|
|
2596
|
+
config.voiceProviderKeys = config.voiceProviderKeys ?? {};
|
|
2597
|
+
config.voiceProviderKeys.grok = env.XAI_API_KEY;
|
|
2598
|
+
}
|
|
2599
|
+
if (env.AGENTICMAIL_VOICE_RUNTIME && env.AGENTICMAIL_VOICE_RUNTIME.trim()) {
|
|
2600
|
+
config.voiceRuntime = env.AGENTICMAIL_VOICE_RUNTIME.trim();
|
|
2601
|
+
}
|
|
2587
2602
|
const configPath = (0, import_node_path.join)(config.dataDir, "config.json");
|
|
2588
2603
|
if ((0, import_node_fs.existsSync)(configPath)) {
|
|
2589
2604
|
try {
|
|
@@ -8678,6 +8693,73 @@ var PhoneManager = class {
|
|
|
8678
8693
|
}]);
|
|
8679
8694
|
return { mission: updated, query: answered, alreadyAnswered: false };
|
|
8680
8695
|
}
|
|
8696
|
+
/**
|
|
8697
|
+
* v0.9.92 — auto-close stale operator queries.
|
|
8698
|
+
*
|
|
8699
|
+
* An operator query is "stale" when:
|
|
8700
|
+
* - it's unanswered, AND
|
|
8701
|
+
* - either (a) the mission is no longer live (status in
|
|
8702
|
+
* {completed, failed, cancelled}), OR (b) the query is older
|
|
8703
|
+
* than `maxAgeSeconds`.
|
|
8704
|
+
*
|
|
8705
|
+
* The sweeper marks each stale query as answered with a synthetic
|
|
8706
|
+
* "[auto-closed: ...]" answer + `answeredVia: 'auto-sweeper'`. This
|
|
8707
|
+
* (a) gets the query out of `listOpenOperatorQueries`, (b) clears
|
|
8708
|
+
* the bridge's "you have N open questions" hint to the operator,
|
|
8709
|
+
* and (c) leaves a permanent audit trail of WHY the query was
|
|
8710
|
+
* closed.
|
|
8711
|
+
*
|
|
8712
|
+
* Returns the count of queries closed + a per-mission breakdown
|
|
8713
|
+
* for logging.
|
|
8714
|
+
*/
|
|
8715
|
+
sweepStaleOperatorQueries(opts = {}) {
|
|
8716
|
+
const maxAgeMs = (opts.maxAgeSeconds ?? 3600) * 1e3;
|
|
8717
|
+
const nowMs = opts.nowMs ?? Date.now();
|
|
8718
|
+
const TERMINAL = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
8719
|
+
const rows = this.db.prepare(
|
|
8720
|
+
`SELECT * FROM phone_missions WHERE metadata_json LIKE '%"operatorQueries"%'`
|
|
8721
|
+
).all();
|
|
8722
|
+
const breakdown = [];
|
|
8723
|
+
let totalClosed = 0;
|
|
8724
|
+
let missionsTouched = 0;
|
|
8725
|
+
for (const row of rows) {
|
|
8726
|
+
const mission = rowToMission(row);
|
|
8727
|
+
const queries = readOperatorQueries(mission);
|
|
8728
|
+
const open = queries.filter((q) => !q.answer);
|
|
8729
|
+
if (open.length === 0) continue;
|
|
8730
|
+
const reason = TERMINAL.has(mission.status) ? "mission-terminal" : null;
|
|
8731
|
+
const closedAt = new Date(nowMs).toISOString();
|
|
8732
|
+
const nextQueries = queries.map((q) => {
|
|
8733
|
+
if (q.answer) return q;
|
|
8734
|
+
const askedAtMs = Date.parse(q.askedAt);
|
|
8735
|
+
const tooOld = Number.isFinite(askedAtMs) && nowMs - askedAtMs >= maxAgeMs;
|
|
8736
|
+
const queryReason = reason ?? (tooOld ? "age" : null);
|
|
8737
|
+
if (!queryReason) return q;
|
|
8738
|
+
return {
|
|
8739
|
+
...q,
|
|
8740
|
+
answer: queryReason === "mission-terminal" ? `[auto-closed: mission ended (${mission.status}) before this question was answered]` : `[auto-closed: question went unanswered for over ${Math.round(maxAgeMs / 6e4)} minutes]`,
|
|
8741
|
+
answeredAt: closedAt,
|
|
8742
|
+
answeredVia: "auto-sweeper"
|
|
8743
|
+
};
|
|
8744
|
+
});
|
|
8745
|
+
const closedHere = nextQueries.filter(
|
|
8746
|
+
(q, i) => q.answer && !queries[i].answer && q.answeredVia === "auto-sweeper"
|
|
8747
|
+
).length;
|
|
8748
|
+
if (closedHere === 0) continue;
|
|
8749
|
+
this.updateMissionStatus(mission.id, mission.status, {
|
|
8750
|
+
operatorQueries: nextQueries
|
|
8751
|
+
}, [{
|
|
8752
|
+
at: closedAt,
|
|
8753
|
+
source: "system",
|
|
8754
|
+
text: `Auto-closed ${closedHere} stale operator query(ies): ${reason ?? "aged out"}.`,
|
|
8755
|
+
metadata: { closedCount: closedHere, reason: reason ?? "age" }
|
|
8756
|
+
}]);
|
|
8757
|
+
totalClosed += closedHere;
|
|
8758
|
+
missionsTouched += 1;
|
|
8759
|
+
breakdown.push({ missionId: mission.id, closed: closedHere, reason: reason ?? "age" });
|
|
8760
|
+
}
|
|
8761
|
+
return { closed: totalClosed, missionsTouched, breakdown };
|
|
8762
|
+
}
|
|
8681
8763
|
// ─── Callback on disconnect (plan §7) ─────────────────
|
|
8682
8764
|
/**
|
|
8683
8765
|
* Flag a mission for callback-on-disconnect: the call dropped while
|
|
@@ -10690,7 +10772,7 @@ var SEARCH_EMAIL_TOOL = {
|
|
|
10690
10772
|
var SEARCH_SKILLS_TOOL = {
|
|
10691
10773
|
type: "function",
|
|
10692
10774
|
name: "search_skills",
|
|
10693
|
-
description:
|
|
10775
|
+
description: 'Search your skill library for a playbook that fits the situation you just hit on this call (billing dispute, debt collector tactics, reservation deadlock, etc). Returns up to 5 ranked matches, each with: id, name, BM25 score, when_to_use (the specific situation the skill is for), first_principle (the playbook\'s strategic frame), and a `recommendation` field. If `recommendation` says LOAD IT NOW or the top score > 0.3, immediately call load_skill with the top id \u2014 do not deliberate. If scores are weak (< 0.15), re-search with a different phrasing instead of loading a poor match. The model that judges "is this the right skill" is YOU \u2014 but the recommendation field will tell you what the right move usually is.',
|
|
10694
10776
|
parameters: {
|
|
10695
10777
|
type: "object",
|
|
10696
10778
|
properties: {
|
|
@@ -12132,6 +12214,94 @@ function withTimeout(promise, ms) {
|
|
|
12132
12214
|
return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));
|
|
12133
12215
|
}
|
|
12134
12216
|
|
|
12217
|
+
// src/phone/voice-providers/registry.ts
|
|
12218
|
+
var PROVIDERS2 = /* @__PURE__ */ new Map();
|
|
12219
|
+
function registerVoiceProvider(provider) {
|
|
12220
|
+
if (PROVIDERS2.has(provider.id)) {
|
|
12221
|
+
throw new Error(`Voice provider "${provider.id}" registered twice \u2014 id collision.`);
|
|
12222
|
+
}
|
|
12223
|
+
PROVIDERS2.set(provider.id, provider);
|
|
12224
|
+
}
|
|
12225
|
+
function listVoiceProviders() {
|
|
12226
|
+
return Array.from(PROVIDERS2.values());
|
|
12227
|
+
}
|
|
12228
|
+
function getVoiceProvider(id) {
|
|
12229
|
+
return PROVIDERS2.get(id);
|
|
12230
|
+
}
|
|
12231
|
+
function resolveVoiceRuntime(providerId, config, options = {}) {
|
|
12232
|
+
const id = (providerId || "openai").trim() || "openai";
|
|
12233
|
+
const provider = PROVIDERS2.get(id);
|
|
12234
|
+
if (!provider) {
|
|
12235
|
+
const known = Array.from(PROVIDERS2.keys()).join(", ") || "(none registered)";
|
|
12236
|
+
throw new Error(
|
|
12237
|
+
`Unknown voice runtime "${id}". Known providers: ${known}. Add a new one by dropping a file into packages/core/src/phone/voice-providers/.`
|
|
12238
|
+
);
|
|
12239
|
+
}
|
|
12240
|
+
let apiKey = "";
|
|
12241
|
+
let apiKeySource = "";
|
|
12242
|
+
if (provider.apiKeyConfigField) {
|
|
12243
|
+
const legacy = config[provider.apiKeyConfigField];
|
|
12244
|
+
if (legacy && legacy.trim()) {
|
|
12245
|
+
apiKey = legacy.trim();
|
|
12246
|
+
apiKeySource = `config.${provider.apiKeyConfigField}`;
|
|
12247
|
+
}
|
|
12248
|
+
}
|
|
12249
|
+
if (!apiKey) {
|
|
12250
|
+
const fromMap = config.voiceProviderKeys?.[provider.id];
|
|
12251
|
+
if (fromMap && fromMap.trim()) {
|
|
12252
|
+
apiKey = fromMap.trim();
|
|
12253
|
+
apiKeySource = `config.voiceProviderKeys.${provider.id}`;
|
|
12254
|
+
}
|
|
12255
|
+
}
|
|
12256
|
+
if (!apiKey) {
|
|
12257
|
+
const fromEnv = process.env[provider.apiKeyEnvVar];
|
|
12258
|
+
if (fromEnv && fromEnv.trim()) {
|
|
12259
|
+
apiKey = fromEnv.trim();
|
|
12260
|
+
apiKeySource = `env ${provider.apiKeyEnvVar}`;
|
|
12261
|
+
}
|
|
12262
|
+
}
|
|
12263
|
+
if (!apiKey) {
|
|
12264
|
+
throw new Error(
|
|
12265
|
+
`Voice provider "${provider.id}" (${provider.displayName}) selected, but no API key is configured. Set ${provider.apiKeyEnvVar} in your environment or save it to ~/.agenticmail/config.json under voiceProviderKeys.${provider.id}.`
|
|
12266
|
+
);
|
|
12267
|
+
}
|
|
12268
|
+
const model = options.model && options.model.trim() || provider.defaultModel;
|
|
12269
|
+
const url = `${provider.websocketBaseUrl}?model=${encodeURIComponent(model)}`;
|
|
12270
|
+
return {
|
|
12271
|
+
providerId: provider.id,
|
|
12272
|
+
providerDisplayName: provider.displayName,
|
|
12273
|
+
url,
|
|
12274
|
+
model,
|
|
12275
|
+
apiKey,
|
|
12276
|
+
apiKeySource
|
|
12277
|
+
};
|
|
12278
|
+
}
|
|
12279
|
+
|
|
12280
|
+
// src/phone/voice-providers/openai.ts
|
|
12281
|
+
registerVoiceProvider({
|
|
12282
|
+
id: "openai",
|
|
12283
|
+
displayName: "OpenAI Realtime (gpt-realtime)",
|
|
12284
|
+
websocketBaseUrl: "wss://api.openai.com/v1/realtime",
|
|
12285
|
+
defaultModel: "gpt-realtime",
|
|
12286
|
+
apiKeyEnvVar: "OPENAI_API_KEY",
|
|
12287
|
+
// Legacy: the original config.json schema used a dedicated
|
|
12288
|
+
// `openaiApiKey` field for this key. The resolver checks that field
|
|
12289
|
+
// before the generic voiceProviderKeys map so existing installs
|
|
12290
|
+
// continue to work without migration.
|
|
12291
|
+
apiKeyConfigField: "openaiApiKey",
|
|
12292
|
+
description: "OpenAI Realtime (gpt-realtime). Default voice runtime; supports linear PCM @ 24 kHz (46elks) and G.711 \xB5-law @ 8 kHz (Twilio) without transcoding."
|
|
12293
|
+
});
|
|
12294
|
+
|
|
12295
|
+
// src/phone/voice-providers/grok.ts
|
|
12296
|
+
registerVoiceProvider({
|
|
12297
|
+
id: "grok",
|
|
12298
|
+
displayName: "xAI Grok Voice Agent",
|
|
12299
|
+
websocketBaseUrl: "wss://api.x.ai/v1/realtime",
|
|
12300
|
+
defaultModel: "grok-voice-latest",
|
|
12301
|
+
apiKeyEnvVar: "XAI_API_KEY",
|
|
12302
|
+
description: 'xAI Grok Voice Agent \u2014 OpenAI-Realtime-compatible WebSocket protocol; select via mission policy.voiceRuntime="grok" or env AGENTICMAIL_VOICE_RUNTIME=grok.'
|
|
12303
|
+
});
|
|
12304
|
+
|
|
12135
12305
|
// src/telemetry.ts
|
|
12136
12306
|
var import_crypto = require("crypto");
|
|
12137
12307
|
var import_fs = require("fs");
|
|
@@ -16446,6 +16616,7 @@ function saveAgentPersona(agentName, content) {
|
|
|
16446
16616
|
getTelegramMe,
|
|
16447
16617
|
getTelegramUpdates,
|
|
16448
16618
|
getTelegramWebhookInfo,
|
|
16619
|
+
getVoiceProvider,
|
|
16449
16620
|
hostSessionStoragePath,
|
|
16450
16621
|
inferPhoneRegion,
|
|
16451
16622
|
invalidateSkillCache,
|
|
@@ -16458,6 +16629,7 @@ function saveAgentPersona(agentName, content) {
|
|
|
16458
16629
|
isTelegramStopCommand,
|
|
16459
16630
|
isValidPhoneNumber,
|
|
16460
16631
|
listSkills,
|
|
16632
|
+
listVoiceProviders,
|
|
16461
16633
|
loadAgentPersona,
|
|
16462
16634
|
loadHostSession,
|
|
16463
16635
|
loadSkill,
|
|
@@ -16486,6 +16658,7 @@ function saveAgentPersona(agentName, content) {
|
|
|
16486
16658
|
redactSecret,
|
|
16487
16659
|
redactSmsConfig,
|
|
16488
16660
|
redactTelegramConfig,
|
|
16661
|
+
registerVoiceProvider,
|
|
16489
16662
|
renderSkillAsPrompt,
|
|
16490
16663
|
requireBinary,
|
|
16491
16664
|
requireWhisperModel,
|
|
@@ -16493,6 +16666,7 @@ function saveAgentPersona(agentName, content) {
|
|
|
16493
16666
|
resolveConfig,
|
|
16494
16667
|
resolveExtensionPolicy,
|
|
16495
16668
|
resolveTlsRejectUnauthorized,
|
|
16669
|
+
resolveVoiceRuntime,
|
|
16496
16670
|
safeJoin,
|
|
16497
16671
|
sanitizeEmail,
|
|
16498
16672
|
saveAgentPersona,
|
package/dist/index.d.cts
CHANGED
|
@@ -229,6 +229,22 @@ interface AgenticMailConfig {
|
|
|
229
229
|
* `config.json`. Optional — no other feature depends on it.
|
|
230
230
|
*/
|
|
231
231
|
openaiApiKey?: string;
|
|
232
|
+
/**
|
|
233
|
+
* v0.9.93 — voice-runtime provider keys. Each is a thin Bearer-token
|
|
234
|
+
* for a provider's realtime API; required only when that provider
|
|
235
|
+
* is selected as the runtime for a call. New providers register
|
|
236
|
+
* themselves in `packages/core/src/phone/voice-providers/` and
|
|
237
|
+
* declare which key field they consume — this record is the central
|
|
238
|
+
* pool. Read from per-provider env vars (e.g. `XAI_API_KEY`) at boot.
|
|
239
|
+
*/
|
|
240
|
+
voiceProviderKeys?: Record<string, string>;
|
|
241
|
+
/**
|
|
242
|
+
* v0.9.93 — default voice-runtime provider id for phone missions
|
|
243
|
+
* that don't pin one on their own policy. `'openai'` (the existing
|
|
244
|
+
* default) or any provider registered in `voice-providers/`.
|
|
245
|
+
* Read from `AGENTICMAIL_VOICE_RUNTIME` env var or `config.json`.
|
|
246
|
+
*/
|
|
247
|
+
voiceRuntime?: string;
|
|
232
248
|
masterKey: string;
|
|
233
249
|
dataDir: string;
|
|
234
250
|
}
|
|
@@ -3824,6 +3840,127 @@ declare class RealtimeVoiceBridge {
|
|
|
3824
3840
|
private safeSend;
|
|
3825
3841
|
}
|
|
3826
3842
|
|
|
3843
|
+
/**
|
|
3844
|
+
* Voice-runtime provider plugin interface.
|
|
3845
|
+
*
|
|
3846
|
+
* Each backend (OpenAI Realtime, Grok Voice Agent, future Anthropic
|
|
3847
|
+
* realtime, Cartesia, ElevenLabs ConvAI, etc.) lives in its own file
|
|
3848
|
+
* under `packages/core/src/phone/voice-providers/` and registers
|
|
3849
|
+
* itself with the registry by calling {@link registerVoiceProvider}
|
|
3850
|
+
* at module load.
|
|
3851
|
+
*
|
|
3852
|
+
* Adding a new provider is meant to be a literal FILE DROP:
|
|
3853
|
+
*
|
|
3854
|
+
* 1. Create `voice-providers/<id>.ts` exporting a {@link VoiceProvider}.
|
|
3855
|
+
* 2. Add a single `import './<id>.js';` line to `voice-providers/index.ts`
|
|
3856
|
+
* so the side-effect registration runs.
|
|
3857
|
+
* 3. (Optional) document the env var the provider expects.
|
|
3858
|
+
*
|
|
3859
|
+
* No other file in the codebase needs to know about the new provider —
|
|
3860
|
+
* the realtime bridge looks providers up by id through the registry.
|
|
3861
|
+
*
|
|
3862
|
+
* Currently every supported provider is an OpenAI-Realtime-compatible
|
|
3863
|
+
* WebSocket. If a future provider diverges enough to need its own wire
|
|
3864
|
+
* protocol (custom event shape, gRPC, WebRTC SDP, etc.), the seam to
|
|
3865
|
+
* extend is here: add `buildSessionUpdate` / `parseInboundEvent` /
|
|
3866
|
+
* etc. hooks to {@link VoiceProvider}, then make `realtime-bridge.ts`
|
|
3867
|
+
* route through them instead of speaking OpenAI Realtime directly.
|
|
3868
|
+
*/
|
|
3869
|
+
/**
|
|
3870
|
+
* One voice-runtime provider. Carries enough information for the
|
|
3871
|
+
* bridge to open the right WebSocket with the right auth + model.
|
|
3872
|
+
*/
|
|
3873
|
+
interface VoiceProvider {
|
|
3874
|
+
/**
|
|
3875
|
+
* Stable identifier used in mission policy / config (`'openai'`,
|
|
3876
|
+
* `'grok'`, …). Keep lowercase, no spaces — this is what operators
|
|
3877
|
+
* type into `AGENTICMAIL_VOICE_RUNTIME=` or pass via mission policy.
|
|
3878
|
+
*/
|
|
3879
|
+
id: string;
|
|
3880
|
+
/** Human-readable display name for logs + the web UI. */
|
|
3881
|
+
displayName: string;
|
|
3882
|
+
/** WebSocket base URL (the bridge appends `?model=…`). */
|
|
3883
|
+
websocketBaseUrl: string;
|
|
3884
|
+
/**
|
|
3885
|
+
* Default model when the caller doesn't pin one. Sent as the
|
|
3886
|
+
* `?model=…` query string AND echoed in the session.update.
|
|
3887
|
+
*/
|
|
3888
|
+
defaultModel: string;
|
|
3889
|
+
/**
|
|
3890
|
+
* The env var the operator sets for this provider's API key
|
|
3891
|
+
* (`OPENAI_API_KEY`, `XAI_API_KEY`, …). The bootstrap / config
|
|
3892
|
+
* loader reads from this name and stores into
|
|
3893
|
+
* `AgenticMailConfig.voiceProviderKeys[<id>]`. Used in the
|
|
3894
|
+
* "you didn't set the key" error message too.
|
|
3895
|
+
*/
|
|
3896
|
+
apiKeyEnvVar: string;
|
|
3897
|
+
/**
|
|
3898
|
+
* Optional fallback config-field name. When the provider's API key
|
|
3899
|
+
* has a long-standing dedicated config field (e.g. OpenAI's
|
|
3900
|
+
* `config.openaiApiKey`), this lets the resolver check that field
|
|
3901
|
+
* BEFORE looking in the generic `voiceProviderKeys` map — so
|
|
3902
|
+
* existing installs don't need to migrate. Leave undefined for
|
|
3903
|
+
* new providers.
|
|
3904
|
+
*/
|
|
3905
|
+
apiKeyConfigField?: 'openaiApiKey';
|
|
3906
|
+
/**
|
|
3907
|
+
* Per-provider notes that surface in error / boot-log messages.
|
|
3908
|
+
* Optional — defaults are fine for the standard providers.
|
|
3909
|
+
*/
|
|
3910
|
+
description?: string;
|
|
3911
|
+
}
|
|
3912
|
+
/**
|
|
3913
|
+
* The bridge needs all the inputs needed to open a session in one
|
|
3914
|
+
* resolved struct — URL with model encoded, the API key, the source
|
|
3915
|
+
* for logging. {@link resolveVoiceRuntime} produces this.
|
|
3916
|
+
*/
|
|
3917
|
+
interface VoiceRuntimeConnection {
|
|
3918
|
+
providerId: string;
|
|
3919
|
+
providerDisplayName: string;
|
|
3920
|
+
/** Full WebSocket URL including `?model=…`. */
|
|
3921
|
+
url: string;
|
|
3922
|
+
/** Resolved model name (also passed in the URL). */
|
|
3923
|
+
model: string;
|
|
3924
|
+
/** Bearer token for the `Authorization` header. */
|
|
3925
|
+
apiKey: string;
|
|
3926
|
+
/** Human-readable source of the key, for boot logs only (e.g. `"env XAI_API_KEY"`). */
|
|
3927
|
+
apiKeySource: string;
|
|
3928
|
+
}
|
|
3929
|
+
|
|
3930
|
+
/**
|
|
3931
|
+
* Voice-provider registry — drop-in plugin discovery.
|
|
3932
|
+
*
|
|
3933
|
+
* Providers register themselves at module-load time via
|
|
3934
|
+
* {@link registerVoiceProvider}. The barrel `voice-providers/index.ts`
|
|
3935
|
+
* imports each provider file for its side effect, populating this map
|
|
3936
|
+
* before any caller asks for one.
|
|
3937
|
+
*
|
|
3938
|
+
* No reflection, no filesystem scan, no decorator magic — adding a
|
|
3939
|
+
* provider is "create a file + add one import line". That gives us
|
|
3940
|
+
* both first-class TypeScript types AND the file-drop ergonomics.
|
|
3941
|
+
*/
|
|
3942
|
+
|
|
3943
|
+
/**
|
|
3944
|
+
* Register a provider. Called once per file at module load. Throws on
|
|
3945
|
+
* duplicate id so an accidental copy-paste collision is loud, not
|
|
3946
|
+
* silently overriding.
|
|
3947
|
+
*/
|
|
3948
|
+
declare function registerVoiceProvider(provider: VoiceProvider): void;
|
|
3949
|
+
/** All registered providers — for `agenticmail voice list` / web UI menus. */
|
|
3950
|
+
declare function listVoiceProviders(): VoiceProvider[];
|
|
3951
|
+
/** Look up a provider by id. Returns undefined for unknown ids. */
|
|
3952
|
+
declare function getVoiceProvider(id: string): VoiceProvider | undefined;
|
|
3953
|
+
/**
|
|
3954
|
+
* Resolve a provider id + the runtime's config / overrides into the
|
|
3955
|
+
* connection struct the bridge consumes (URL with model, api key,
|
|
3956
|
+
* source). Throws if the provider id is unknown or its API key isn't
|
|
3957
|
+
* configured — the realtime-ws layer turns the throw into a clear
|
|
3958
|
+
* startup error instead of a mid-call surprise.
|
|
3959
|
+
*/
|
|
3960
|
+
declare function resolveVoiceRuntime(providerId: string | undefined, config: AgenticMailConfig, options?: {
|
|
3961
|
+
model?: string;
|
|
3962
|
+
}): VoiceRuntimeConnection;
|
|
3963
|
+
|
|
3827
3964
|
type PhoneTransportProvider = '46elks' | 'twilio';
|
|
3828
3965
|
/** Providers that support starting outbound call-control missions. */
|
|
3829
3966
|
declare const PHONE_CALL_CONTROL_PROVIDERS: readonly PhoneTransportProvider[];
|
|
@@ -4109,6 +4246,37 @@ declare class PhoneManager {
|
|
|
4109
4246
|
query: PhoneOperatorQuery;
|
|
4110
4247
|
alreadyAnswered: boolean;
|
|
4111
4248
|
} | null;
|
|
4249
|
+
/**
|
|
4250
|
+
* v0.9.92 — auto-close stale operator queries.
|
|
4251
|
+
*
|
|
4252
|
+
* An operator query is "stale" when:
|
|
4253
|
+
* - it's unanswered, AND
|
|
4254
|
+
* - either (a) the mission is no longer live (status in
|
|
4255
|
+
* {completed, failed, cancelled}), OR (b) the query is older
|
|
4256
|
+
* than `maxAgeSeconds`.
|
|
4257
|
+
*
|
|
4258
|
+
* The sweeper marks each stale query as answered with a synthetic
|
|
4259
|
+
* "[auto-closed: ...]" answer + `answeredVia: 'auto-sweeper'`. This
|
|
4260
|
+
* (a) gets the query out of `listOpenOperatorQueries`, (b) clears
|
|
4261
|
+
* the bridge's "you have N open questions" hint to the operator,
|
|
4262
|
+
* and (c) leaves a permanent audit trail of WHY the query was
|
|
4263
|
+
* closed.
|
|
4264
|
+
*
|
|
4265
|
+
* Returns the count of queries closed + a per-mission breakdown
|
|
4266
|
+
* for logging.
|
|
4267
|
+
*/
|
|
4268
|
+
sweepStaleOperatorQueries(opts?: {
|
|
4269
|
+
maxAgeSeconds?: number;
|
|
4270
|
+
nowMs?: number;
|
|
4271
|
+
}): {
|
|
4272
|
+
closed: number;
|
|
4273
|
+
missionsTouched: number;
|
|
4274
|
+
breakdown: Array<{
|
|
4275
|
+
missionId: string;
|
|
4276
|
+
closed: number;
|
|
4277
|
+
reason: 'mission-terminal' | 'age';
|
|
4278
|
+
}>;
|
|
4279
|
+
};
|
|
4112
4280
|
/**
|
|
4113
4281
|
* Flag a mission for callback-on-disconnect: the call dropped while
|
|
4114
4282
|
* an operator query was still unanswered, so once the operator
|
|
@@ -6010,6 +6178,32 @@ interface SkillSummary {
|
|
|
6010
6178
|
version: string;
|
|
6011
6179
|
disclaimer_required: boolean;
|
|
6012
6180
|
estimated_call_duration_minutes: number;
|
|
6181
|
+
/**
|
|
6182
|
+
* v0.9.92 — surfaced from `context.when_to_use`. This is the field
|
|
6183
|
+
* that actually tells the model "should I load this for the
|
|
6184
|
+
* current situation?" — far more diagnostic than the generic
|
|
6185
|
+
* `description` (which is just a one-liner for browsing). The
|
|
6186
|
+
* realtime `search_skills` tool result includes it so the model
|
|
6187
|
+
* can decide WITHOUT a second `load_skill` round-trip on a wrong
|
|
6188
|
+
* guess.
|
|
6189
|
+
*/
|
|
6190
|
+
when_to_use: string;
|
|
6191
|
+
/**
|
|
6192
|
+
* v0.9.92 — the skill's first principle, surfaced for the same
|
|
6193
|
+
* "is this the right playbook" decision. Principles are the
|
|
6194
|
+
* strategic frame ("be calm and friendly — the rep didn't choose
|
|
6195
|
+
* your bill"); seeing one principle tells the model whether the
|
|
6196
|
+
* skill's POSTURE matches the situation, not just its topic.
|
|
6197
|
+
*/
|
|
6198
|
+
first_principle: string;
|
|
6199
|
+
/**
|
|
6200
|
+
* v0.9.92 — BM25F search score from the rank. Only present on
|
|
6201
|
+
* results from `searchSkills`; absent on `listSkills` output
|
|
6202
|
+
* (where the ordering is by id, not by relevance). Lets the
|
|
6203
|
+
* model thresholds "definitely load" vs. "re-search with a
|
|
6204
|
+
* better query".
|
|
6205
|
+
*/
|
|
6206
|
+
score?: number;
|
|
6013
6207
|
}
|
|
6014
6208
|
/** Failed-validation result from the schema validator. */
|
|
6015
6209
|
interface SkillValidationError {
|
|
@@ -6191,4 +6385,4 @@ declare function loadAgentPersona(agentName: string): string;
|
|
|
6191
6385
|
*/
|
|
6192
6386
|
declare function saveAgentPersona(agentName: string, content: string): string;
|
|
6193
6387
|
|
|
6194
|
-
export { AGENT_ROLES, AGENT_STATE_ROOT, ASK_OPERATOR_TOOL, AccountManager, type AddressInfo, type Agent, AgentDeletionService, type AgentMemoryEntry, type AgentMemoryFields, AgentMemoryManager, type AgentMemoryOptions, type AgentMemoryRead, AgentMemoryStore, type AgentRole, AgenticMailClient, type AgenticMailClientOptions, type AgenticMailConfig, type ArchiveAndDeleteOptions, type ArchivedEmail, type Attachment, type AttachmentAdvisory, type AudioAction, type AudioEditOptions, BRIDGE_OPERATOR_LIVE_WINDOW_MS, type BridgeMailContext, type BridgeWakeError, type BridgeWakePromptArgs, type BridgeWakeResult, type BridgeWakeRoute, type CachedMessage, CloudflareClient, type CreateAgentOptions, type CreateMemoryInput, DEFAULT_AGENT_NAME, DEFAULT_AGENT_ROLE, DEFAULT_CALLBACK_POLICY, DEFAULT_EXTENSION_POLICY, DEFAULT_REALTIME_AUDIO_FORMAT, DEFAULT_REALTIME_MODEL, DEFAULT_REALTIME_VOICE, DEFAULT_SESSION_MAX_AGE_MS, DEFAULT_WEB_SEARCH_ENDPOINT, DNSConfigurator, type Database, type DeletionReport, type DeletionSummary, DependencyChecker, DependencyInstaller, type DependencyStatus, type DnsRecord, type DnsSetupResult, type DomainInfo, DomainManager, type DomainModeConfig, type DomainPurchaseResult, DomainPurchaser, type DomainSearchResult, type DomainSetupResult, ELKS_REALTIME_AUDIO_FORMATS, ELKS_REALTIME_WS_PATH, END_CALL_TOOL, EXTEND_CALL_TIME_TOOL, type ElksRealtimeAudioFormat, type ElksRealtimeAudioMessage, type ElksRealtimeByeMessage, type ElksRealtimeHelloMessage, type ElksRealtimeInboundMessage, type ElksRealtimeOutboundMessage, ElksRealtimeTransport, type EmailEnvelope, type EmailRouteAction, type EmailRouteClass, type EmailRouteClassification, type EmailRouteInput, EmailSearchIndex, type FolderInfo, GET_CALL_STATUS_TOOL, GET_DATETIME_TOOL, type GatewayConfig, GatewayManager, type GatewayManagerOptions, type GatewayMode, type GatewayStatus, type GetDatetimeOptions, type GetUpdatesOptions, type HostName, type HostSession, type HostSessionResumeMode, type ImageAction, type ImageEditOptions, type InboundEmail, type InboundSmsEvent, type InboxEvent, type InboxExpungeEvent, type InboxFlagsEvent, type InboxNewEvent, InboxWatcher, type InboxWatcherOptions, type InstallProgress, LOAD_SKILL_TOOL, type LinkAdvisory, type LocalSmtpConfig, MEMORY_CATEGORIES, MailReceiver, type MailReceiverOptions, MailSender, type MailSenderOptions, type MailboxInfo, type MediaBinary, type MediaCapability, type MediaCapabilityReport, type MediaFileResult, type MediaInfoResult, MediaManager, type MediaManagerOptions, type MediaStreamInfo, type MemoryCategory, type MemoryImportance, type MemoryQueryOptions, type MemoryRecaller, MemorySearchIndex, type MemorySource, type MemoryStats, OPENAI_REALTIME_URL, OPERATOR_QUERY_POLL_INTERVAL_MS, OPERATOR_QUERY_SUBJECT_TAG, OPERATOR_QUERY_TIMEOUT_MS, OPERATOR_QUERY_TIMEOUT_SENTINEL, type OpenClawPhoneMissionPolicy, type OperatorQueryNotificationInput, type OperatorQueryPollOptions, type OperatorQueryUrgency, type OperatorReplyKind, type OutboundCategory, type OutboundScanInput, type OutboundScanResult, type OutboundWarning, PERSONA_FILENAME, PHONE_CALLBACK_MAX_DELAY_SECONDS, PHONE_CALLBACK_MIN_DELAY_SECONDS, PHONE_CALL_CONTROL_PROVIDERS, PHONE_MAX_CONCURRENT_MISSIONS, PHONE_MIN_WEBHOOK_SECRET_LENGTH, PHONE_MISSION_STATES, PHONE_RATE_LIMIT_PER_HOUR, PHONE_RATE_LIMIT_PER_MINUTE, PHONE_REGION_SCOPES, PHONE_SERVER_MAX_ATTEMPTS, PHONE_SERVER_MAX_CALLBACK_CHAIN, PHONE_SERVER_MAX_CALL_DURATION_SECONDS, PHONE_SERVER_MAX_COST_PER_MISSION, PHONE_SERVER_MAX_EXTENSION_REQUESTS_PER_CALL, PHONE_SERVER_MAX_EXTENSION_SECONDS_PER_REQUEST, PHONE_SERVER_MAX_TOTAL_EXTENSION_SECONDS, PHONE_TASK_MAX_LENGTH, type ParsedAttachment, type ParsedEmail, type ParsedOperatorReply, type ParsedSms, type ParsedTelegramMessage, PathTraversalError, type PhoneAlternativePolicy, type PhoneCallMission, type PhoneCallbackPolicy, type PhoneConfirmPolicy, type PhoneExtensionPolicy, PhoneManager, type PhoneMissionStartValidationResult, type PhoneMissionState, type PhoneMissionTranscriptEntry, type PhoneMissionValidationIssue, type PhoneMissionValidationResult, type PhoneNumberRisk, type PhoneOperatorQuery, PhoneRateLimitError, type PhoneRegionScope, type PhoneScheduledCallback, type PhoneTransportConfig, type PhoneTransportProfile, type PhoneTransportProvider, type PhoneTransportValidationResult, PhoneWebhookAuthError, type PhoneWebhookResult, type PlanBridgeWakeArgs, type PurchasedDomain, REALTIME_AUDIO_SAMPLE_RATE, REALTIME_MAX_AUDIO_FRAME_BASE64, REALTIME_TOOL_CALL_TIMEOUT_MS, REALTIME_TOOL_DEFINITIONS, RECALL_MEMORY_TOOL, REDACTED, RELAY_PRESETS, type RealtimeBridgePort, type RealtimeBridgeTranscriptEntry, type RealtimeInboundEvent, type RealtimeInstructionOptions, type RealtimeSessionConfigOptions, type RealtimeToolCall, type RealtimeToolDefinition, type RealtimeToolHandler, type RealtimeToolResult, type RealtimeTransportAdapter, type RealtimeTransportProvider, RealtimeVoiceBridge, type RealtimeVoiceBridgeOptions, RelayBridge, type RelayBridgeOptions, type RelayConfig, RelayGateway, type RelayProvider, type RelaySearchResult, type ResumeErrorClassificationOptions, SCHEDULE_CALLBACK_TOOL, SEARCH_EMAIL_TOOL, SEARCH_SKILLS_TOOL, SPAM_THRESHOLD, type SafeJoinOptions, type SanitizeDetection, type SanitizeResult, type ScheduledCallbackRequest, type SearchCriteria, type SearchableEmail, type SecurityAdvisory, type SendMailOptions, type SendResult, type SendResultWithRaw, type SendSmsInput, type SendSmsResult, type SendTelegramMessageOptions, type SendTelegramMessageResult, ServiceManager, type ServiceStatus, type SetWebhookOptions, type SetupConfig, SetupManager, type SetupResult, type Severity, type Skill, type SkillCategory, type SkillContext, type SkillExitStrategy, type SkillSummary, type SkillTactic, type SkillValidationError, type SmsConfig, SmsManager, type SmsMessage, SmsPoller, type SmsProvider, type SpamCategory, type SpamResult, type SpamRuleMatch, StalwartAdmin, type StalwartAdminOptions, type StalwartPrincipal, type StartPhoneCallOptions, type StartPhoneCallResult, type StartPhoneMissionInput, TELEGRAM_API_BASE, TELEGRAM_CHUNK_SIZE, TELEGRAM_MESSAGE_LIMIT, TELEGRAM_MIN_WEBHOOK_SECRET_LENGTH, TELEGRAM_OPERATOR_QUERY_TAG, TELEGRAM_STOP_WORDS, TELEGRAM_WEBHOOK_SECRET_RE, TELEPHONY_TRANSPORT_CAPABILITIES, TWILIO_MEDIA_SAMPLE_RATE, TWILIO_REALTIME_WS_PATH, TelegramApiError, type TelegramApiOptions, type TelegramBotInfo, type TelegramChatType, type TelegramConfig, TelegramManager, type TelegramMessage, type TelegramMode, type TelephonyTransportCapability, ThreadCache, type ThreadCacheEntry, type ThreadCacheOptions, type ThreadIdInput, type ToolExecutor, type TtsGenerateOptions, type TunnelConfig, TunnelManager, type TwilioConnectedMessage, type TwilioMarkMessage, type TwilioMediaMessage, type TwilioRealtimeInboundMessage, type TwilioRealtimeOutboundMessage, TwilioRealtimeTransport, type TwilioStartMessage, type TwilioStopMessage, type TwilioStreamTwiMLOptions, UnsafeApiUrlError, type UpdateMemoryInput, type ValidatedPhoneMissionStart, type VideoAction, type VideoEditOptions, type VideoTimelineEntry, type VideoUnderstandOptions, type VideoUnderstandResult, type VoiceCloneOptions, WARNING_THRESHOLD, WEB_SEARCH_TOOL, WEB_SEARCH_UNTRUSTED_PREFIX, type WatcherOptions, type WebSearchOptions, assertWithinBase, bridgeWakeErrorMessage, bridgeWakeLastSeenAgeMs, buildApiUrl, buildDefaultPersona, buildElksAudioMessage, buildElksByeMessage, buildElksHandshakeMessages, buildElksInterruptMessage, buildElksListeningMessage, buildElksSendingMessage, buildInboundSecurityAdvisory, buildOpenAIRealtimeUrl, buildPhoneTransportConfig, buildRealtimeInstructions, buildRealtimeSessionConfig, buildRealtimeToolGuidance, buildTwilioClearMessage, buildTwilioMarkMessage, buildTwilioMediaMessage, buildTwilioSayTwiML, buildTwilioSignature, buildTwilioStreamTwiML, callTelegramApi, classifyEmailRoute, classifyPhoneNumberRisk, classifyResumeError, clearMediaCapabilityCache, closeDatabase, composeBridgeWakePrompt, createRealtimeTransport, createTestDatabase, createToolExecutor, debug, debugWarn, deleteTelegramWebhook, detectBinary, ensureDataDir, escapeXml, extractEmailAddress, extractVerificationCode, flushTelemetry, forgetHostSession, formatOperatorQueryTelegramMessage, getDatabase, getDatetime, getMediaCapabilities, getOperatorEmail, getSmsProvider, getTelegramChat, getTelegramMe, getTelegramUpdates, getTelegramWebhookInfo, hostSessionStoragePath, inferPhoneRegion, invalidateSkillCache, isInternalEmail, isLoopbackMailHost, isOperatorReplySender, isPhoneRegionAllowed, isSessionFresh, isTelegramChatAllowed, isTelegramStopCommand, isValidPhoneNumber, listSkills, loadAgentPersona, loadHostSession, loadSkill, mapProviderSmsStatus, nextTelegramOffset, normalizeAddress, normalizePhoneNumber, normalizeSubject, operatorPrefsStoragePath, operatorQuerySubject, parseElksRealtimeMessage, parseEmail, parseGoogleVoiceSms, parseOperatorQueryReply, parseTelegramOperatorReply, parseTelegramUpdate, parseTwilioRealtimeMessage, personaPathFor, planBridgeWake, pollForOperatorAnswer, recallMemory, recordToolCall, redactBotToken, redactObject, redactPhoneTransportConfig, redactSecret, redactSmsConfig, redactTelegramConfig, renderSkillAsPrompt, requireBinary, requireWhisperModel, resolveCallbackPolicy, resolveConfig, resolveExtensionPolicy, resolveTlsRejectUnauthorized, safeJoin, sanitizeEmail, saveAgentPersona, saveConfig, saveHostSession, saveUserSkill, scanOutboundEmail, scoreEmail, searchSkills, sendTelegramMessage, setOperatorEmail, setTelegramWebhook, setTelemetryVersion, shouldSkipBridgeWakeForLiveOperator, splitTelegramMessage, startRelayBridge, stem, stripTelegramMarkdown, threadIdFor, tokenize, tryJoin, userSkillsDir, validateApiUrl, validatePhoneMissionPolicy, validatePhoneMissionStart, validatePhoneTransportProfile, validateSkill, validateTwilioSignature, webSearch };
|
|
6388
|
+
export { AGENT_ROLES, AGENT_STATE_ROOT, ASK_OPERATOR_TOOL, AccountManager, type AddressInfo, type Agent, AgentDeletionService, type AgentMemoryEntry, type AgentMemoryFields, AgentMemoryManager, type AgentMemoryOptions, type AgentMemoryRead, AgentMemoryStore, type AgentRole, AgenticMailClient, type AgenticMailClientOptions, type AgenticMailConfig, type ArchiveAndDeleteOptions, type ArchivedEmail, type Attachment, type AttachmentAdvisory, type AudioAction, type AudioEditOptions, BRIDGE_OPERATOR_LIVE_WINDOW_MS, type BridgeMailContext, type BridgeWakeError, type BridgeWakePromptArgs, type BridgeWakeResult, type BridgeWakeRoute, type CachedMessage, CloudflareClient, type CreateAgentOptions, type CreateMemoryInput, DEFAULT_AGENT_NAME, DEFAULT_AGENT_ROLE, DEFAULT_CALLBACK_POLICY, DEFAULT_EXTENSION_POLICY, DEFAULT_REALTIME_AUDIO_FORMAT, DEFAULT_REALTIME_MODEL, DEFAULT_REALTIME_VOICE, DEFAULT_SESSION_MAX_AGE_MS, DEFAULT_WEB_SEARCH_ENDPOINT, DNSConfigurator, type Database, type DeletionReport, type DeletionSummary, DependencyChecker, DependencyInstaller, type DependencyStatus, type DnsRecord, type DnsSetupResult, type DomainInfo, DomainManager, type DomainModeConfig, type DomainPurchaseResult, DomainPurchaser, type DomainSearchResult, type DomainSetupResult, ELKS_REALTIME_AUDIO_FORMATS, ELKS_REALTIME_WS_PATH, END_CALL_TOOL, EXTEND_CALL_TIME_TOOL, type ElksRealtimeAudioFormat, type ElksRealtimeAudioMessage, type ElksRealtimeByeMessage, type ElksRealtimeHelloMessage, type ElksRealtimeInboundMessage, type ElksRealtimeOutboundMessage, ElksRealtimeTransport, type EmailEnvelope, type EmailRouteAction, type EmailRouteClass, type EmailRouteClassification, type EmailRouteInput, EmailSearchIndex, type FolderInfo, GET_CALL_STATUS_TOOL, GET_DATETIME_TOOL, type GatewayConfig, GatewayManager, type GatewayManagerOptions, type GatewayMode, type GatewayStatus, type GetDatetimeOptions, type GetUpdatesOptions, type HostName, type HostSession, type HostSessionResumeMode, type ImageAction, type ImageEditOptions, type InboundEmail, type InboundSmsEvent, type InboxEvent, type InboxExpungeEvent, type InboxFlagsEvent, type InboxNewEvent, InboxWatcher, type InboxWatcherOptions, type InstallProgress, LOAD_SKILL_TOOL, type LinkAdvisory, type LocalSmtpConfig, MEMORY_CATEGORIES, MailReceiver, type MailReceiverOptions, MailSender, type MailSenderOptions, type MailboxInfo, type MediaBinary, type MediaCapability, type MediaCapabilityReport, type MediaFileResult, type MediaInfoResult, MediaManager, type MediaManagerOptions, type MediaStreamInfo, type MemoryCategory, type MemoryImportance, type MemoryQueryOptions, type MemoryRecaller, MemorySearchIndex, type MemorySource, type MemoryStats, OPENAI_REALTIME_URL, OPERATOR_QUERY_POLL_INTERVAL_MS, OPERATOR_QUERY_SUBJECT_TAG, OPERATOR_QUERY_TIMEOUT_MS, OPERATOR_QUERY_TIMEOUT_SENTINEL, type OpenClawPhoneMissionPolicy, type OperatorQueryNotificationInput, type OperatorQueryPollOptions, type OperatorQueryUrgency, type OperatorReplyKind, type OutboundCategory, type OutboundScanInput, type OutboundScanResult, type OutboundWarning, PERSONA_FILENAME, PHONE_CALLBACK_MAX_DELAY_SECONDS, PHONE_CALLBACK_MIN_DELAY_SECONDS, PHONE_CALL_CONTROL_PROVIDERS, PHONE_MAX_CONCURRENT_MISSIONS, PHONE_MIN_WEBHOOK_SECRET_LENGTH, PHONE_MISSION_STATES, PHONE_RATE_LIMIT_PER_HOUR, PHONE_RATE_LIMIT_PER_MINUTE, PHONE_REGION_SCOPES, PHONE_SERVER_MAX_ATTEMPTS, PHONE_SERVER_MAX_CALLBACK_CHAIN, PHONE_SERVER_MAX_CALL_DURATION_SECONDS, PHONE_SERVER_MAX_COST_PER_MISSION, PHONE_SERVER_MAX_EXTENSION_REQUESTS_PER_CALL, PHONE_SERVER_MAX_EXTENSION_SECONDS_PER_REQUEST, PHONE_SERVER_MAX_TOTAL_EXTENSION_SECONDS, PHONE_TASK_MAX_LENGTH, type ParsedAttachment, type ParsedEmail, type ParsedOperatorReply, type ParsedSms, type ParsedTelegramMessage, PathTraversalError, type PhoneAlternativePolicy, type PhoneCallMission, type PhoneCallbackPolicy, type PhoneConfirmPolicy, type PhoneExtensionPolicy, PhoneManager, type PhoneMissionStartValidationResult, type PhoneMissionState, type PhoneMissionTranscriptEntry, type PhoneMissionValidationIssue, type PhoneMissionValidationResult, type PhoneNumberRisk, type PhoneOperatorQuery, PhoneRateLimitError, type PhoneRegionScope, type PhoneScheduledCallback, type PhoneTransportConfig, type PhoneTransportProfile, type PhoneTransportProvider, type PhoneTransportValidationResult, PhoneWebhookAuthError, type PhoneWebhookResult, type PlanBridgeWakeArgs, type PurchasedDomain, REALTIME_AUDIO_SAMPLE_RATE, REALTIME_MAX_AUDIO_FRAME_BASE64, REALTIME_TOOL_CALL_TIMEOUT_MS, REALTIME_TOOL_DEFINITIONS, RECALL_MEMORY_TOOL, REDACTED, RELAY_PRESETS, type RealtimeBridgePort, type RealtimeBridgeTranscriptEntry, type RealtimeInboundEvent, type RealtimeInstructionOptions, type RealtimeSessionConfigOptions, type RealtimeToolCall, type RealtimeToolDefinition, type RealtimeToolHandler, type RealtimeToolResult, type RealtimeTransportAdapter, type RealtimeTransportProvider, RealtimeVoiceBridge, type RealtimeVoiceBridgeOptions, RelayBridge, type RelayBridgeOptions, type RelayConfig, RelayGateway, type RelayProvider, type RelaySearchResult, type ResumeErrorClassificationOptions, SCHEDULE_CALLBACK_TOOL, SEARCH_EMAIL_TOOL, SEARCH_SKILLS_TOOL, SPAM_THRESHOLD, type SafeJoinOptions, type SanitizeDetection, type SanitizeResult, type ScheduledCallbackRequest, type SearchCriteria, type SearchableEmail, type SecurityAdvisory, type SendMailOptions, type SendResult, type SendResultWithRaw, type SendSmsInput, type SendSmsResult, type SendTelegramMessageOptions, type SendTelegramMessageResult, ServiceManager, type ServiceStatus, type SetWebhookOptions, type SetupConfig, SetupManager, type SetupResult, type Severity, type Skill, type SkillCategory, type SkillContext, type SkillExitStrategy, type SkillSummary, type SkillTactic, type SkillValidationError, type SmsConfig, SmsManager, type SmsMessage, SmsPoller, type SmsProvider, type SpamCategory, type SpamResult, type SpamRuleMatch, StalwartAdmin, type StalwartAdminOptions, type StalwartPrincipal, type StartPhoneCallOptions, type StartPhoneCallResult, type StartPhoneMissionInput, TELEGRAM_API_BASE, TELEGRAM_CHUNK_SIZE, TELEGRAM_MESSAGE_LIMIT, TELEGRAM_MIN_WEBHOOK_SECRET_LENGTH, TELEGRAM_OPERATOR_QUERY_TAG, TELEGRAM_STOP_WORDS, TELEGRAM_WEBHOOK_SECRET_RE, TELEPHONY_TRANSPORT_CAPABILITIES, TWILIO_MEDIA_SAMPLE_RATE, TWILIO_REALTIME_WS_PATH, TelegramApiError, type TelegramApiOptions, type TelegramBotInfo, type TelegramChatType, type TelegramConfig, TelegramManager, type TelegramMessage, type TelegramMode, type TelephonyTransportCapability, ThreadCache, type ThreadCacheEntry, type ThreadCacheOptions, type ThreadIdInput, type ToolExecutor, type TtsGenerateOptions, type TunnelConfig, TunnelManager, type TwilioConnectedMessage, type TwilioMarkMessage, type TwilioMediaMessage, type TwilioRealtimeInboundMessage, type TwilioRealtimeOutboundMessage, TwilioRealtimeTransport, type TwilioStartMessage, type TwilioStopMessage, type TwilioStreamTwiMLOptions, UnsafeApiUrlError, type UpdateMemoryInput, type ValidatedPhoneMissionStart, type VideoAction, type VideoEditOptions, type VideoTimelineEntry, type VideoUnderstandOptions, type VideoUnderstandResult, type VoiceCloneOptions, type VoiceProvider, type VoiceRuntimeConnection, WARNING_THRESHOLD, WEB_SEARCH_TOOL, WEB_SEARCH_UNTRUSTED_PREFIX, type WatcherOptions, type WebSearchOptions, assertWithinBase, bridgeWakeErrorMessage, bridgeWakeLastSeenAgeMs, buildApiUrl, buildDefaultPersona, buildElksAudioMessage, buildElksByeMessage, buildElksHandshakeMessages, buildElksInterruptMessage, buildElksListeningMessage, buildElksSendingMessage, buildInboundSecurityAdvisory, buildOpenAIRealtimeUrl, buildPhoneTransportConfig, buildRealtimeInstructions, buildRealtimeSessionConfig, buildRealtimeToolGuidance, buildTwilioClearMessage, buildTwilioMarkMessage, buildTwilioMediaMessage, buildTwilioSayTwiML, buildTwilioSignature, buildTwilioStreamTwiML, callTelegramApi, classifyEmailRoute, classifyPhoneNumberRisk, classifyResumeError, clearMediaCapabilityCache, closeDatabase, composeBridgeWakePrompt, createRealtimeTransport, createTestDatabase, createToolExecutor, debug, debugWarn, deleteTelegramWebhook, detectBinary, ensureDataDir, escapeXml, extractEmailAddress, extractVerificationCode, flushTelemetry, forgetHostSession, formatOperatorQueryTelegramMessage, getDatabase, getDatetime, getMediaCapabilities, getOperatorEmail, getSmsProvider, getTelegramChat, getTelegramMe, getTelegramUpdates, getTelegramWebhookInfo, getVoiceProvider, hostSessionStoragePath, inferPhoneRegion, invalidateSkillCache, isInternalEmail, isLoopbackMailHost, isOperatorReplySender, isPhoneRegionAllowed, isSessionFresh, isTelegramChatAllowed, isTelegramStopCommand, isValidPhoneNumber, listSkills, listVoiceProviders, loadAgentPersona, loadHostSession, loadSkill, mapProviderSmsStatus, nextTelegramOffset, normalizeAddress, normalizePhoneNumber, normalizeSubject, operatorPrefsStoragePath, operatorQuerySubject, parseElksRealtimeMessage, parseEmail, parseGoogleVoiceSms, parseOperatorQueryReply, parseTelegramOperatorReply, parseTelegramUpdate, parseTwilioRealtimeMessage, personaPathFor, planBridgeWake, pollForOperatorAnswer, recallMemory, recordToolCall, redactBotToken, redactObject, redactPhoneTransportConfig, redactSecret, redactSmsConfig, redactTelegramConfig, registerVoiceProvider, renderSkillAsPrompt, requireBinary, requireWhisperModel, resolveCallbackPolicy, resolveConfig, resolveExtensionPolicy, resolveTlsRejectUnauthorized, resolveVoiceRuntime, safeJoin, sanitizeEmail, saveAgentPersona, saveConfig, saveHostSession, saveUserSkill, scanOutboundEmail, scoreEmail, searchSkills, sendTelegramMessage, setOperatorEmail, setTelegramWebhook, setTelemetryVersion, shouldSkipBridgeWakeForLiveOperator, splitTelegramMessage, startRelayBridge, stem, stripTelegramMarkdown, threadIdFor, tokenize, tryJoin, userSkillsDir, validateApiUrl, validatePhoneMissionPolicy, validatePhoneMissionStart, validatePhoneTransportProfile, validateSkill, validateTwilioSignature, webSearch };
|
package/dist/index.d.ts
CHANGED
|
@@ -229,6 +229,22 @@ interface AgenticMailConfig {
|
|
|
229
229
|
* `config.json`. Optional — no other feature depends on it.
|
|
230
230
|
*/
|
|
231
231
|
openaiApiKey?: string;
|
|
232
|
+
/**
|
|
233
|
+
* v0.9.93 — voice-runtime provider keys. Each is a thin Bearer-token
|
|
234
|
+
* for a provider's realtime API; required only when that provider
|
|
235
|
+
* is selected as the runtime for a call. New providers register
|
|
236
|
+
* themselves in `packages/core/src/phone/voice-providers/` and
|
|
237
|
+
* declare which key field they consume — this record is the central
|
|
238
|
+
* pool. Read from per-provider env vars (e.g. `XAI_API_KEY`) at boot.
|
|
239
|
+
*/
|
|
240
|
+
voiceProviderKeys?: Record<string, string>;
|
|
241
|
+
/**
|
|
242
|
+
* v0.9.93 — default voice-runtime provider id for phone missions
|
|
243
|
+
* that don't pin one on their own policy. `'openai'` (the existing
|
|
244
|
+
* default) or any provider registered in `voice-providers/`.
|
|
245
|
+
* Read from `AGENTICMAIL_VOICE_RUNTIME` env var or `config.json`.
|
|
246
|
+
*/
|
|
247
|
+
voiceRuntime?: string;
|
|
232
248
|
masterKey: string;
|
|
233
249
|
dataDir: string;
|
|
234
250
|
}
|
|
@@ -3824,6 +3840,127 @@ declare class RealtimeVoiceBridge {
|
|
|
3824
3840
|
private safeSend;
|
|
3825
3841
|
}
|
|
3826
3842
|
|
|
3843
|
+
/**
|
|
3844
|
+
* Voice-runtime provider plugin interface.
|
|
3845
|
+
*
|
|
3846
|
+
* Each backend (OpenAI Realtime, Grok Voice Agent, future Anthropic
|
|
3847
|
+
* realtime, Cartesia, ElevenLabs ConvAI, etc.) lives in its own file
|
|
3848
|
+
* under `packages/core/src/phone/voice-providers/` and registers
|
|
3849
|
+
* itself with the registry by calling {@link registerVoiceProvider}
|
|
3850
|
+
* at module load.
|
|
3851
|
+
*
|
|
3852
|
+
* Adding a new provider is meant to be a literal FILE DROP:
|
|
3853
|
+
*
|
|
3854
|
+
* 1. Create `voice-providers/<id>.ts` exporting a {@link VoiceProvider}.
|
|
3855
|
+
* 2. Add a single `import './<id>.js';` line to `voice-providers/index.ts`
|
|
3856
|
+
* so the side-effect registration runs.
|
|
3857
|
+
* 3. (Optional) document the env var the provider expects.
|
|
3858
|
+
*
|
|
3859
|
+
* No other file in the codebase needs to know about the new provider —
|
|
3860
|
+
* the realtime bridge looks providers up by id through the registry.
|
|
3861
|
+
*
|
|
3862
|
+
* Currently every supported provider is an OpenAI-Realtime-compatible
|
|
3863
|
+
* WebSocket. If a future provider diverges enough to need its own wire
|
|
3864
|
+
* protocol (custom event shape, gRPC, WebRTC SDP, etc.), the seam to
|
|
3865
|
+
* extend is here: add `buildSessionUpdate` / `parseInboundEvent` /
|
|
3866
|
+
* etc. hooks to {@link VoiceProvider}, then make `realtime-bridge.ts`
|
|
3867
|
+
* route through them instead of speaking OpenAI Realtime directly.
|
|
3868
|
+
*/
|
|
3869
|
+
/**
|
|
3870
|
+
* One voice-runtime provider. Carries enough information for the
|
|
3871
|
+
* bridge to open the right WebSocket with the right auth + model.
|
|
3872
|
+
*/
|
|
3873
|
+
interface VoiceProvider {
|
|
3874
|
+
/**
|
|
3875
|
+
* Stable identifier used in mission policy / config (`'openai'`,
|
|
3876
|
+
* `'grok'`, …). Keep lowercase, no spaces — this is what operators
|
|
3877
|
+
* type into `AGENTICMAIL_VOICE_RUNTIME=` or pass via mission policy.
|
|
3878
|
+
*/
|
|
3879
|
+
id: string;
|
|
3880
|
+
/** Human-readable display name for logs + the web UI. */
|
|
3881
|
+
displayName: string;
|
|
3882
|
+
/** WebSocket base URL (the bridge appends `?model=…`). */
|
|
3883
|
+
websocketBaseUrl: string;
|
|
3884
|
+
/**
|
|
3885
|
+
* Default model when the caller doesn't pin one. Sent as the
|
|
3886
|
+
* `?model=…` query string AND echoed in the session.update.
|
|
3887
|
+
*/
|
|
3888
|
+
defaultModel: string;
|
|
3889
|
+
/**
|
|
3890
|
+
* The env var the operator sets for this provider's API key
|
|
3891
|
+
* (`OPENAI_API_KEY`, `XAI_API_KEY`, …). The bootstrap / config
|
|
3892
|
+
* loader reads from this name and stores into
|
|
3893
|
+
* `AgenticMailConfig.voiceProviderKeys[<id>]`. Used in the
|
|
3894
|
+
* "you didn't set the key" error message too.
|
|
3895
|
+
*/
|
|
3896
|
+
apiKeyEnvVar: string;
|
|
3897
|
+
/**
|
|
3898
|
+
* Optional fallback config-field name. When the provider's API key
|
|
3899
|
+
* has a long-standing dedicated config field (e.g. OpenAI's
|
|
3900
|
+
* `config.openaiApiKey`), this lets the resolver check that field
|
|
3901
|
+
* BEFORE looking in the generic `voiceProviderKeys` map — so
|
|
3902
|
+
* existing installs don't need to migrate. Leave undefined for
|
|
3903
|
+
* new providers.
|
|
3904
|
+
*/
|
|
3905
|
+
apiKeyConfigField?: 'openaiApiKey';
|
|
3906
|
+
/**
|
|
3907
|
+
* Per-provider notes that surface in error / boot-log messages.
|
|
3908
|
+
* Optional — defaults are fine for the standard providers.
|
|
3909
|
+
*/
|
|
3910
|
+
description?: string;
|
|
3911
|
+
}
|
|
3912
|
+
/**
|
|
3913
|
+
* The bridge needs all the inputs needed to open a session in one
|
|
3914
|
+
* resolved struct — URL with model encoded, the API key, the source
|
|
3915
|
+
* for logging. {@link resolveVoiceRuntime} produces this.
|
|
3916
|
+
*/
|
|
3917
|
+
interface VoiceRuntimeConnection {
|
|
3918
|
+
providerId: string;
|
|
3919
|
+
providerDisplayName: string;
|
|
3920
|
+
/** Full WebSocket URL including `?model=…`. */
|
|
3921
|
+
url: string;
|
|
3922
|
+
/** Resolved model name (also passed in the URL). */
|
|
3923
|
+
model: string;
|
|
3924
|
+
/** Bearer token for the `Authorization` header. */
|
|
3925
|
+
apiKey: string;
|
|
3926
|
+
/** Human-readable source of the key, for boot logs only (e.g. `"env XAI_API_KEY"`). */
|
|
3927
|
+
apiKeySource: string;
|
|
3928
|
+
}
|
|
3929
|
+
|
|
3930
|
+
/**
|
|
3931
|
+
* Voice-provider registry — drop-in plugin discovery.
|
|
3932
|
+
*
|
|
3933
|
+
* Providers register themselves at module-load time via
|
|
3934
|
+
* {@link registerVoiceProvider}. The barrel `voice-providers/index.ts`
|
|
3935
|
+
* imports each provider file for its side effect, populating this map
|
|
3936
|
+
* before any caller asks for one.
|
|
3937
|
+
*
|
|
3938
|
+
* No reflection, no filesystem scan, no decorator magic — adding a
|
|
3939
|
+
* provider is "create a file + add one import line". That gives us
|
|
3940
|
+
* both first-class TypeScript types AND the file-drop ergonomics.
|
|
3941
|
+
*/
|
|
3942
|
+
|
|
3943
|
+
/**
|
|
3944
|
+
* Register a provider. Called once per file at module load. Throws on
|
|
3945
|
+
* duplicate id so an accidental copy-paste collision is loud, not
|
|
3946
|
+
* silently overriding.
|
|
3947
|
+
*/
|
|
3948
|
+
declare function registerVoiceProvider(provider: VoiceProvider): void;
|
|
3949
|
+
/** All registered providers — for `agenticmail voice list` / web UI menus. */
|
|
3950
|
+
declare function listVoiceProviders(): VoiceProvider[];
|
|
3951
|
+
/** Look up a provider by id. Returns undefined for unknown ids. */
|
|
3952
|
+
declare function getVoiceProvider(id: string): VoiceProvider | undefined;
|
|
3953
|
+
/**
|
|
3954
|
+
* Resolve a provider id + the runtime's config / overrides into the
|
|
3955
|
+
* connection struct the bridge consumes (URL with model, api key,
|
|
3956
|
+
* source). Throws if the provider id is unknown or its API key isn't
|
|
3957
|
+
* configured — the realtime-ws layer turns the throw into a clear
|
|
3958
|
+
* startup error instead of a mid-call surprise.
|
|
3959
|
+
*/
|
|
3960
|
+
declare function resolveVoiceRuntime(providerId: string | undefined, config: AgenticMailConfig, options?: {
|
|
3961
|
+
model?: string;
|
|
3962
|
+
}): VoiceRuntimeConnection;
|
|
3963
|
+
|
|
3827
3964
|
type PhoneTransportProvider = '46elks' | 'twilio';
|
|
3828
3965
|
/** Providers that support starting outbound call-control missions. */
|
|
3829
3966
|
declare const PHONE_CALL_CONTROL_PROVIDERS: readonly PhoneTransportProvider[];
|
|
@@ -4109,6 +4246,37 @@ declare class PhoneManager {
|
|
|
4109
4246
|
query: PhoneOperatorQuery;
|
|
4110
4247
|
alreadyAnswered: boolean;
|
|
4111
4248
|
} | null;
|
|
4249
|
+
/**
|
|
4250
|
+
* v0.9.92 — auto-close stale operator queries.
|
|
4251
|
+
*
|
|
4252
|
+
* An operator query is "stale" when:
|
|
4253
|
+
* - it's unanswered, AND
|
|
4254
|
+
* - either (a) the mission is no longer live (status in
|
|
4255
|
+
* {completed, failed, cancelled}), OR (b) the query is older
|
|
4256
|
+
* than `maxAgeSeconds`.
|
|
4257
|
+
*
|
|
4258
|
+
* The sweeper marks each stale query as answered with a synthetic
|
|
4259
|
+
* "[auto-closed: ...]" answer + `answeredVia: 'auto-sweeper'`. This
|
|
4260
|
+
* (a) gets the query out of `listOpenOperatorQueries`, (b) clears
|
|
4261
|
+
* the bridge's "you have N open questions" hint to the operator,
|
|
4262
|
+
* and (c) leaves a permanent audit trail of WHY the query was
|
|
4263
|
+
* closed.
|
|
4264
|
+
*
|
|
4265
|
+
* Returns the count of queries closed + a per-mission breakdown
|
|
4266
|
+
* for logging.
|
|
4267
|
+
*/
|
|
4268
|
+
sweepStaleOperatorQueries(opts?: {
|
|
4269
|
+
maxAgeSeconds?: number;
|
|
4270
|
+
nowMs?: number;
|
|
4271
|
+
}): {
|
|
4272
|
+
closed: number;
|
|
4273
|
+
missionsTouched: number;
|
|
4274
|
+
breakdown: Array<{
|
|
4275
|
+
missionId: string;
|
|
4276
|
+
closed: number;
|
|
4277
|
+
reason: 'mission-terminal' | 'age';
|
|
4278
|
+
}>;
|
|
4279
|
+
};
|
|
4112
4280
|
/**
|
|
4113
4281
|
* Flag a mission for callback-on-disconnect: the call dropped while
|
|
4114
4282
|
* an operator query was still unanswered, so once the operator
|
|
@@ -6010,6 +6178,32 @@ interface SkillSummary {
|
|
|
6010
6178
|
version: string;
|
|
6011
6179
|
disclaimer_required: boolean;
|
|
6012
6180
|
estimated_call_duration_minutes: number;
|
|
6181
|
+
/**
|
|
6182
|
+
* v0.9.92 — surfaced from `context.when_to_use`. This is the field
|
|
6183
|
+
* that actually tells the model "should I load this for the
|
|
6184
|
+
* current situation?" — far more diagnostic than the generic
|
|
6185
|
+
* `description` (which is just a one-liner for browsing). The
|
|
6186
|
+
* realtime `search_skills` tool result includes it so the model
|
|
6187
|
+
* can decide WITHOUT a second `load_skill` round-trip on a wrong
|
|
6188
|
+
* guess.
|
|
6189
|
+
*/
|
|
6190
|
+
when_to_use: string;
|
|
6191
|
+
/**
|
|
6192
|
+
* v0.9.92 — the skill's first principle, surfaced for the same
|
|
6193
|
+
* "is this the right playbook" decision. Principles are the
|
|
6194
|
+
* strategic frame ("be calm and friendly — the rep didn't choose
|
|
6195
|
+
* your bill"); seeing one principle tells the model whether the
|
|
6196
|
+
* skill's POSTURE matches the situation, not just its topic.
|
|
6197
|
+
*/
|
|
6198
|
+
first_principle: string;
|
|
6199
|
+
/**
|
|
6200
|
+
* v0.9.92 — BM25F search score from the rank. Only present on
|
|
6201
|
+
* results from `searchSkills`; absent on `listSkills` output
|
|
6202
|
+
* (where the ordering is by id, not by relevance). Lets the
|
|
6203
|
+
* model thresholds "definitely load" vs. "re-search with a
|
|
6204
|
+
* better query".
|
|
6205
|
+
*/
|
|
6206
|
+
score?: number;
|
|
6013
6207
|
}
|
|
6014
6208
|
/** Failed-validation result from the schema validator. */
|
|
6015
6209
|
interface SkillValidationError {
|
|
@@ -6191,4 +6385,4 @@ declare function loadAgentPersona(agentName: string): string;
|
|
|
6191
6385
|
*/
|
|
6192
6386
|
declare function saveAgentPersona(agentName: string, content: string): string;
|
|
6193
6387
|
|
|
6194
|
-
export { AGENT_ROLES, AGENT_STATE_ROOT, ASK_OPERATOR_TOOL, AccountManager, type AddressInfo, type Agent, AgentDeletionService, type AgentMemoryEntry, type AgentMemoryFields, AgentMemoryManager, type AgentMemoryOptions, type AgentMemoryRead, AgentMemoryStore, type AgentRole, AgenticMailClient, type AgenticMailClientOptions, type AgenticMailConfig, type ArchiveAndDeleteOptions, type ArchivedEmail, type Attachment, type AttachmentAdvisory, type AudioAction, type AudioEditOptions, BRIDGE_OPERATOR_LIVE_WINDOW_MS, type BridgeMailContext, type BridgeWakeError, type BridgeWakePromptArgs, type BridgeWakeResult, type BridgeWakeRoute, type CachedMessage, CloudflareClient, type CreateAgentOptions, type CreateMemoryInput, DEFAULT_AGENT_NAME, DEFAULT_AGENT_ROLE, DEFAULT_CALLBACK_POLICY, DEFAULT_EXTENSION_POLICY, DEFAULT_REALTIME_AUDIO_FORMAT, DEFAULT_REALTIME_MODEL, DEFAULT_REALTIME_VOICE, DEFAULT_SESSION_MAX_AGE_MS, DEFAULT_WEB_SEARCH_ENDPOINT, DNSConfigurator, type Database, type DeletionReport, type DeletionSummary, DependencyChecker, DependencyInstaller, type DependencyStatus, type DnsRecord, type DnsSetupResult, type DomainInfo, DomainManager, type DomainModeConfig, type DomainPurchaseResult, DomainPurchaser, type DomainSearchResult, type DomainSetupResult, ELKS_REALTIME_AUDIO_FORMATS, ELKS_REALTIME_WS_PATH, END_CALL_TOOL, EXTEND_CALL_TIME_TOOL, type ElksRealtimeAudioFormat, type ElksRealtimeAudioMessage, type ElksRealtimeByeMessage, type ElksRealtimeHelloMessage, type ElksRealtimeInboundMessage, type ElksRealtimeOutboundMessage, ElksRealtimeTransport, type EmailEnvelope, type EmailRouteAction, type EmailRouteClass, type EmailRouteClassification, type EmailRouteInput, EmailSearchIndex, type FolderInfo, GET_CALL_STATUS_TOOL, GET_DATETIME_TOOL, type GatewayConfig, GatewayManager, type GatewayManagerOptions, type GatewayMode, type GatewayStatus, type GetDatetimeOptions, type GetUpdatesOptions, type HostName, type HostSession, type HostSessionResumeMode, type ImageAction, type ImageEditOptions, type InboundEmail, type InboundSmsEvent, type InboxEvent, type InboxExpungeEvent, type InboxFlagsEvent, type InboxNewEvent, InboxWatcher, type InboxWatcherOptions, type InstallProgress, LOAD_SKILL_TOOL, type LinkAdvisory, type LocalSmtpConfig, MEMORY_CATEGORIES, MailReceiver, type MailReceiverOptions, MailSender, type MailSenderOptions, type MailboxInfo, type MediaBinary, type MediaCapability, type MediaCapabilityReport, type MediaFileResult, type MediaInfoResult, MediaManager, type MediaManagerOptions, type MediaStreamInfo, type MemoryCategory, type MemoryImportance, type MemoryQueryOptions, type MemoryRecaller, MemorySearchIndex, type MemorySource, type MemoryStats, OPENAI_REALTIME_URL, OPERATOR_QUERY_POLL_INTERVAL_MS, OPERATOR_QUERY_SUBJECT_TAG, OPERATOR_QUERY_TIMEOUT_MS, OPERATOR_QUERY_TIMEOUT_SENTINEL, type OpenClawPhoneMissionPolicy, type OperatorQueryNotificationInput, type OperatorQueryPollOptions, type OperatorQueryUrgency, type OperatorReplyKind, type OutboundCategory, type OutboundScanInput, type OutboundScanResult, type OutboundWarning, PERSONA_FILENAME, PHONE_CALLBACK_MAX_DELAY_SECONDS, PHONE_CALLBACK_MIN_DELAY_SECONDS, PHONE_CALL_CONTROL_PROVIDERS, PHONE_MAX_CONCURRENT_MISSIONS, PHONE_MIN_WEBHOOK_SECRET_LENGTH, PHONE_MISSION_STATES, PHONE_RATE_LIMIT_PER_HOUR, PHONE_RATE_LIMIT_PER_MINUTE, PHONE_REGION_SCOPES, PHONE_SERVER_MAX_ATTEMPTS, PHONE_SERVER_MAX_CALLBACK_CHAIN, PHONE_SERVER_MAX_CALL_DURATION_SECONDS, PHONE_SERVER_MAX_COST_PER_MISSION, PHONE_SERVER_MAX_EXTENSION_REQUESTS_PER_CALL, PHONE_SERVER_MAX_EXTENSION_SECONDS_PER_REQUEST, PHONE_SERVER_MAX_TOTAL_EXTENSION_SECONDS, PHONE_TASK_MAX_LENGTH, type ParsedAttachment, type ParsedEmail, type ParsedOperatorReply, type ParsedSms, type ParsedTelegramMessage, PathTraversalError, type PhoneAlternativePolicy, type PhoneCallMission, type PhoneCallbackPolicy, type PhoneConfirmPolicy, type PhoneExtensionPolicy, PhoneManager, type PhoneMissionStartValidationResult, type PhoneMissionState, type PhoneMissionTranscriptEntry, type PhoneMissionValidationIssue, type PhoneMissionValidationResult, type PhoneNumberRisk, type PhoneOperatorQuery, PhoneRateLimitError, type PhoneRegionScope, type PhoneScheduledCallback, type PhoneTransportConfig, type PhoneTransportProfile, type PhoneTransportProvider, type PhoneTransportValidationResult, PhoneWebhookAuthError, type PhoneWebhookResult, type PlanBridgeWakeArgs, type PurchasedDomain, REALTIME_AUDIO_SAMPLE_RATE, REALTIME_MAX_AUDIO_FRAME_BASE64, REALTIME_TOOL_CALL_TIMEOUT_MS, REALTIME_TOOL_DEFINITIONS, RECALL_MEMORY_TOOL, REDACTED, RELAY_PRESETS, type RealtimeBridgePort, type RealtimeBridgeTranscriptEntry, type RealtimeInboundEvent, type RealtimeInstructionOptions, type RealtimeSessionConfigOptions, type RealtimeToolCall, type RealtimeToolDefinition, type RealtimeToolHandler, type RealtimeToolResult, type RealtimeTransportAdapter, type RealtimeTransportProvider, RealtimeVoiceBridge, type RealtimeVoiceBridgeOptions, RelayBridge, type RelayBridgeOptions, type RelayConfig, RelayGateway, type RelayProvider, type RelaySearchResult, type ResumeErrorClassificationOptions, SCHEDULE_CALLBACK_TOOL, SEARCH_EMAIL_TOOL, SEARCH_SKILLS_TOOL, SPAM_THRESHOLD, type SafeJoinOptions, type SanitizeDetection, type SanitizeResult, type ScheduledCallbackRequest, type SearchCriteria, type SearchableEmail, type SecurityAdvisory, type SendMailOptions, type SendResult, type SendResultWithRaw, type SendSmsInput, type SendSmsResult, type SendTelegramMessageOptions, type SendTelegramMessageResult, ServiceManager, type ServiceStatus, type SetWebhookOptions, type SetupConfig, SetupManager, type SetupResult, type Severity, type Skill, type SkillCategory, type SkillContext, type SkillExitStrategy, type SkillSummary, type SkillTactic, type SkillValidationError, type SmsConfig, SmsManager, type SmsMessage, SmsPoller, type SmsProvider, type SpamCategory, type SpamResult, type SpamRuleMatch, StalwartAdmin, type StalwartAdminOptions, type StalwartPrincipal, type StartPhoneCallOptions, type StartPhoneCallResult, type StartPhoneMissionInput, TELEGRAM_API_BASE, TELEGRAM_CHUNK_SIZE, TELEGRAM_MESSAGE_LIMIT, TELEGRAM_MIN_WEBHOOK_SECRET_LENGTH, TELEGRAM_OPERATOR_QUERY_TAG, TELEGRAM_STOP_WORDS, TELEGRAM_WEBHOOK_SECRET_RE, TELEPHONY_TRANSPORT_CAPABILITIES, TWILIO_MEDIA_SAMPLE_RATE, TWILIO_REALTIME_WS_PATH, TelegramApiError, type TelegramApiOptions, type TelegramBotInfo, type TelegramChatType, type TelegramConfig, TelegramManager, type TelegramMessage, type TelegramMode, type TelephonyTransportCapability, ThreadCache, type ThreadCacheEntry, type ThreadCacheOptions, type ThreadIdInput, type ToolExecutor, type TtsGenerateOptions, type TunnelConfig, TunnelManager, type TwilioConnectedMessage, type TwilioMarkMessage, type TwilioMediaMessage, type TwilioRealtimeInboundMessage, type TwilioRealtimeOutboundMessage, TwilioRealtimeTransport, type TwilioStartMessage, type TwilioStopMessage, type TwilioStreamTwiMLOptions, UnsafeApiUrlError, type UpdateMemoryInput, type ValidatedPhoneMissionStart, type VideoAction, type VideoEditOptions, type VideoTimelineEntry, type VideoUnderstandOptions, type VideoUnderstandResult, type VoiceCloneOptions, WARNING_THRESHOLD, WEB_SEARCH_TOOL, WEB_SEARCH_UNTRUSTED_PREFIX, type WatcherOptions, type WebSearchOptions, assertWithinBase, bridgeWakeErrorMessage, bridgeWakeLastSeenAgeMs, buildApiUrl, buildDefaultPersona, buildElksAudioMessage, buildElksByeMessage, buildElksHandshakeMessages, buildElksInterruptMessage, buildElksListeningMessage, buildElksSendingMessage, buildInboundSecurityAdvisory, buildOpenAIRealtimeUrl, buildPhoneTransportConfig, buildRealtimeInstructions, buildRealtimeSessionConfig, buildRealtimeToolGuidance, buildTwilioClearMessage, buildTwilioMarkMessage, buildTwilioMediaMessage, buildTwilioSayTwiML, buildTwilioSignature, buildTwilioStreamTwiML, callTelegramApi, classifyEmailRoute, classifyPhoneNumberRisk, classifyResumeError, clearMediaCapabilityCache, closeDatabase, composeBridgeWakePrompt, createRealtimeTransport, createTestDatabase, createToolExecutor, debug, debugWarn, deleteTelegramWebhook, detectBinary, ensureDataDir, escapeXml, extractEmailAddress, extractVerificationCode, flushTelemetry, forgetHostSession, formatOperatorQueryTelegramMessage, getDatabase, getDatetime, getMediaCapabilities, getOperatorEmail, getSmsProvider, getTelegramChat, getTelegramMe, getTelegramUpdates, getTelegramWebhookInfo, hostSessionStoragePath, inferPhoneRegion, invalidateSkillCache, isInternalEmail, isLoopbackMailHost, isOperatorReplySender, isPhoneRegionAllowed, isSessionFresh, isTelegramChatAllowed, isTelegramStopCommand, isValidPhoneNumber, listSkills, loadAgentPersona, loadHostSession, loadSkill, mapProviderSmsStatus, nextTelegramOffset, normalizeAddress, normalizePhoneNumber, normalizeSubject, operatorPrefsStoragePath, operatorQuerySubject, parseElksRealtimeMessage, parseEmail, parseGoogleVoiceSms, parseOperatorQueryReply, parseTelegramOperatorReply, parseTelegramUpdate, parseTwilioRealtimeMessage, personaPathFor, planBridgeWake, pollForOperatorAnswer, recallMemory, recordToolCall, redactBotToken, redactObject, redactPhoneTransportConfig, redactSecret, redactSmsConfig, redactTelegramConfig, renderSkillAsPrompt, requireBinary, requireWhisperModel, resolveCallbackPolicy, resolveConfig, resolveExtensionPolicy, resolveTlsRejectUnauthorized, safeJoin, sanitizeEmail, saveAgentPersona, saveConfig, saveHostSession, saveUserSkill, scanOutboundEmail, scoreEmail, searchSkills, sendTelegramMessage, setOperatorEmail, setTelegramWebhook, setTelemetryVersion, shouldSkipBridgeWakeForLiveOperator, splitTelegramMessage, startRelayBridge, stem, stripTelegramMarkdown, threadIdFor, tokenize, tryJoin, userSkillsDir, validateApiUrl, validatePhoneMissionPolicy, validatePhoneMissionStart, validatePhoneTransportProfile, validateSkill, validateTwilioSignature, webSearch };
|
|
6388
|
+
export { AGENT_ROLES, AGENT_STATE_ROOT, ASK_OPERATOR_TOOL, AccountManager, type AddressInfo, type Agent, AgentDeletionService, type AgentMemoryEntry, type AgentMemoryFields, AgentMemoryManager, type AgentMemoryOptions, type AgentMemoryRead, AgentMemoryStore, type AgentRole, AgenticMailClient, type AgenticMailClientOptions, type AgenticMailConfig, type ArchiveAndDeleteOptions, type ArchivedEmail, type Attachment, type AttachmentAdvisory, type AudioAction, type AudioEditOptions, BRIDGE_OPERATOR_LIVE_WINDOW_MS, type BridgeMailContext, type BridgeWakeError, type BridgeWakePromptArgs, type BridgeWakeResult, type BridgeWakeRoute, type CachedMessage, CloudflareClient, type CreateAgentOptions, type CreateMemoryInput, DEFAULT_AGENT_NAME, DEFAULT_AGENT_ROLE, DEFAULT_CALLBACK_POLICY, DEFAULT_EXTENSION_POLICY, DEFAULT_REALTIME_AUDIO_FORMAT, DEFAULT_REALTIME_MODEL, DEFAULT_REALTIME_VOICE, DEFAULT_SESSION_MAX_AGE_MS, DEFAULT_WEB_SEARCH_ENDPOINT, DNSConfigurator, type Database, type DeletionReport, type DeletionSummary, DependencyChecker, DependencyInstaller, type DependencyStatus, type DnsRecord, type DnsSetupResult, type DomainInfo, DomainManager, type DomainModeConfig, type DomainPurchaseResult, DomainPurchaser, type DomainSearchResult, type DomainSetupResult, ELKS_REALTIME_AUDIO_FORMATS, ELKS_REALTIME_WS_PATH, END_CALL_TOOL, EXTEND_CALL_TIME_TOOL, type ElksRealtimeAudioFormat, type ElksRealtimeAudioMessage, type ElksRealtimeByeMessage, type ElksRealtimeHelloMessage, type ElksRealtimeInboundMessage, type ElksRealtimeOutboundMessage, ElksRealtimeTransport, type EmailEnvelope, type EmailRouteAction, type EmailRouteClass, type EmailRouteClassification, type EmailRouteInput, EmailSearchIndex, type FolderInfo, GET_CALL_STATUS_TOOL, GET_DATETIME_TOOL, type GatewayConfig, GatewayManager, type GatewayManagerOptions, type GatewayMode, type GatewayStatus, type GetDatetimeOptions, type GetUpdatesOptions, type HostName, type HostSession, type HostSessionResumeMode, type ImageAction, type ImageEditOptions, type InboundEmail, type InboundSmsEvent, type InboxEvent, type InboxExpungeEvent, type InboxFlagsEvent, type InboxNewEvent, InboxWatcher, type InboxWatcherOptions, type InstallProgress, LOAD_SKILL_TOOL, type LinkAdvisory, type LocalSmtpConfig, MEMORY_CATEGORIES, MailReceiver, type MailReceiverOptions, MailSender, type MailSenderOptions, type MailboxInfo, type MediaBinary, type MediaCapability, type MediaCapabilityReport, type MediaFileResult, type MediaInfoResult, MediaManager, type MediaManagerOptions, type MediaStreamInfo, type MemoryCategory, type MemoryImportance, type MemoryQueryOptions, type MemoryRecaller, MemorySearchIndex, type MemorySource, type MemoryStats, OPENAI_REALTIME_URL, OPERATOR_QUERY_POLL_INTERVAL_MS, OPERATOR_QUERY_SUBJECT_TAG, OPERATOR_QUERY_TIMEOUT_MS, OPERATOR_QUERY_TIMEOUT_SENTINEL, type OpenClawPhoneMissionPolicy, type OperatorQueryNotificationInput, type OperatorQueryPollOptions, type OperatorQueryUrgency, type OperatorReplyKind, type OutboundCategory, type OutboundScanInput, type OutboundScanResult, type OutboundWarning, PERSONA_FILENAME, PHONE_CALLBACK_MAX_DELAY_SECONDS, PHONE_CALLBACK_MIN_DELAY_SECONDS, PHONE_CALL_CONTROL_PROVIDERS, PHONE_MAX_CONCURRENT_MISSIONS, PHONE_MIN_WEBHOOK_SECRET_LENGTH, PHONE_MISSION_STATES, PHONE_RATE_LIMIT_PER_HOUR, PHONE_RATE_LIMIT_PER_MINUTE, PHONE_REGION_SCOPES, PHONE_SERVER_MAX_ATTEMPTS, PHONE_SERVER_MAX_CALLBACK_CHAIN, PHONE_SERVER_MAX_CALL_DURATION_SECONDS, PHONE_SERVER_MAX_COST_PER_MISSION, PHONE_SERVER_MAX_EXTENSION_REQUESTS_PER_CALL, PHONE_SERVER_MAX_EXTENSION_SECONDS_PER_REQUEST, PHONE_SERVER_MAX_TOTAL_EXTENSION_SECONDS, PHONE_TASK_MAX_LENGTH, type ParsedAttachment, type ParsedEmail, type ParsedOperatorReply, type ParsedSms, type ParsedTelegramMessage, PathTraversalError, type PhoneAlternativePolicy, type PhoneCallMission, type PhoneCallbackPolicy, type PhoneConfirmPolicy, type PhoneExtensionPolicy, PhoneManager, type PhoneMissionStartValidationResult, type PhoneMissionState, type PhoneMissionTranscriptEntry, type PhoneMissionValidationIssue, type PhoneMissionValidationResult, type PhoneNumberRisk, type PhoneOperatorQuery, PhoneRateLimitError, type PhoneRegionScope, type PhoneScheduledCallback, type PhoneTransportConfig, type PhoneTransportProfile, type PhoneTransportProvider, type PhoneTransportValidationResult, PhoneWebhookAuthError, type PhoneWebhookResult, type PlanBridgeWakeArgs, type PurchasedDomain, REALTIME_AUDIO_SAMPLE_RATE, REALTIME_MAX_AUDIO_FRAME_BASE64, REALTIME_TOOL_CALL_TIMEOUT_MS, REALTIME_TOOL_DEFINITIONS, RECALL_MEMORY_TOOL, REDACTED, RELAY_PRESETS, type RealtimeBridgePort, type RealtimeBridgeTranscriptEntry, type RealtimeInboundEvent, type RealtimeInstructionOptions, type RealtimeSessionConfigOptions, type RealtimeToolCall, type RealtimeToolDefinition, type RealtimeToolHandler, type RealtimeToolResult, type RealtimeTransportAdapter, type RealtimeTransportProvider, RealtimeVoiceBridge, type RealtimeVoiceBridgeOptions, RelayBridge, type RelayBridgeOptions, type RelayConfig, RelayGateway, type RelayProvider, type RelaySearchResult, type ResumeErrorClassificationOptions, SCHEDULE_CALLBACK_TOOL, SEARCH_EMAIL_TOOL, SEARCH_SKILLS_TOOL, SPAM_THRESHOLD, type SafeJoinOptions, type SanitizeDetection, type SanitizeResult, type ScheduledCallbackRequest, type SearchCriteria, type SearchableEmail, type SecurityAdvisory, type SendMailOptions, type SendResult, type SendResultWithRaw, type SendSmsInput, type SendSmsResult, type SendTelegramMessageOptions, type SendTelegramMessageResult, ServiceManager, type ServiceStatus, type SetWebhookOptions, type SetupConfig, SetupManager, type SetupResult, type Severity, type Skill, type SkillCategory, type SkillContext, type SkillExitStrategy, type SkillSummary, type SkillTactic, type SkillValidationError, type SmsConfig, SmsManager, type SmsMessage, SmsPoller, type SmsProvider, type SpamCategory, type SpamResult, type SpamRuleMatch, StalwartAdmin, type StalwartAdminOptions, type StalwartPrincipal, type StartPhoneCallOptions, type StartPhoneCallResult, type StartPhoneMissionInput, TELEGRAM_API_BASE, TELEGRAM_CHUNK_SIZE, TELEGRAM_MESSAGE_LIMIT, TELEGRAM_MIN_WEBHOOK_SECRET_LENGTH, TELEGRAM_OPERATOR_QUERY_TAG, TELEGRAM_STOP_WORDS, TELEGRAM_WEBHOOK_SECRET_RE, TELEPHONY_TRANSPORT_CAPABILITIES, TWILIO_MEDIA_SAMPLE_RATE, TWILIO_REALTIME_WS_PATH, TelegramApiError, type TelegramApiOptions, type TelegramBotInfo, type TelegramChatType, type TelegramConfig, TelegramManager, type TelegramMessage, type TelegramMode, type TelephonyTransportCapability, ThreadCache, type ThreadCacheEntry, type ThreadCacheOptions, type ThreadIdInput, type ToolExecutor, type TtsGenerateOptions, type TunnelConfig, TunnelManager, type TwilioConnectedMessage, type TwilioMarkMessage, type TwilioMediaMessage, type TwilioRealtimeInboundMessage, type TwilioRealtimeOutboundMessage, TwilioRealtimeTransport, type TwilioStartMessage, type TwilioStopMessage, type TwilioStreamTwiMLOptions, UnsafeApiUrlError, type UpdateMemoryInput, type ValidatedPhoneMissionStart, type VideoAction, type VideoEditOptions, type VideoTimelineEntry, type VideoUnderstandOptions, type VideoUnderstandResult, type VoiceCloneOptions, type VoiceProvider, type VoiceRuntimeConnection, WARNING_THRESHOLD, WEB_SEARCH_TOOL, WEB_SEARCH_UNTRUSTED_PREFIX, type WatcherOptions, type WebSearchOptions, assertWithinBase, bridgeWakeErrorMessage, bridgeWakeLastSeenAgeMs, buildApiUrl, buildDefaultPersona, buildElksAudioMessage, buildElksByeMessage, buildElksHandshakeMessages, buildElksInterruptMessage, buildElksListeningMessage, buildElksSendingMessage, buildInboundSecurityAdvisory, buildOpenAIRealtimeUrl, buildPhoneTransportConfig, buildRealtimeInstructions, buildRealtimeSessionConfig, buildRealtimeToolGuidance, buildTwilioClearMessage, buildTwilioMarkMessage, buildTwilioMediaMessage, buildTwilioSayTwiML, buildTwilioSignature, buildTwilioStreamTwiML, callTelegramApi, classifyEmailRoute, classifyPhoneNumberRisk, classifyResumeError, clearMediaCapabilityCache, closeDatabase, composeBridgeWakePrompt, createRealtimeTransport, createTestDatabase, createToolExecutor, debug, debugWarn, deleteTelegramWebhook, detectBinary, ensureDataDir, escapeXml, extractEmailAddress, extractVerificationCode, flushTelemetry, forgetHostSession, formatOperatorQueryTelegramMessage, getDatabase, getDatetime, getMediaCapabilities, getOperatorEmail, getSmsProvider, getTelegramChat, getTelegramMe, getTelegramUpdates, getTelegramWebhookInfo, getVoiceProvider, hostSessionStoragePath, inferPhoneRegion, invalidateSkillCache, isInternalEmail, isLoopbackMailHost, isOperatorReplySender, isPhoneRegionAllowed, isSessionFresh, isTelegramChatAllowed, isTelegramStopCommand, isValidPhoneNumber, listSkills, listVoiceProviders, loadAgentPersona, loadHostSession, loadSkill, mapProviderSmsStatus, nextTelegramOffset, normalizeAddress, normalizePhoneNumber, normalizeSubject, operatorPrefsStoragePath, operatorQuerySubject, parseElksRealtimeMessage, parseEmail, parseGoogleVoiceSms, parseOperatorQueryReply, parseTelegramOperatorReply, parseTelegramUpdate, parseTwilioRealtimeMessage, personaPathFor, planBridgeWake, pollForOperatorAnswer, recallMemory, recordToolCall, redactBotToken, redactObject, redactPhoneTransportConfig, redactSecret, redactSmsConfig, redactTelegramConfig, registerVoiceProvider, renderSkillAsPrompt, requireBinary, requireWhisperModel, resolveCallbackPolicy, resolveConfig, resolveExtensionPolicy, resolveTlsRejectUnauthorized, resolveVoiceRuntime, safeJoin, sanitizeEmail, saveAgentPersona, saveConfig, saveHostSession, saveUserSkill, scanOutboundEmail, scoreEmail, searchSkills, sendTelegramMessage, setOperatorEmail, setTelegramWebhook, setTelemetryVersion, shouldSkipBridgeWakeForLiveOperator, splitTelegramMessage, startRelayBridge, stem, stripTelegramMarkdown, threadIdFor, tokenize, tryJoin, userSkillsDir, validateApiUrl, validatePhoneMissionPolicy, validatePhoneMissionStart, validatePhoneTransportProfile, validateSkill, validateTwilioSignature, webSearch };
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
tokenize,
|
|
17
17
|
userSkillsDir,
|
|
18
18
|
validateSkill
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-FYULLCZX.js";
|
|
20
20
|
import {
|
|
21
21
|
__require
|
|
22
22
|
} from "./chunk-3RG5ZIWI.js";
|
|
@@ -920,6 +920,13 @@ function resolveConfig(overrides) {
|
|
|
920
920
|
dataDir: env.AGENTICMAIL_DATA_DIR?.replace(/^~(?=\/|$)/, homedir()) ?? DEFAULT_CONFIG.dataDir
|
|
921
921
|
};
|
|
922
922
|
if (env.OPENAI_API_KEY) config.openaiApiKey = env.OPENAI_API_KEY;
|
|
923
|
+
if (env.XAI_API_KEY) {
|
|
924
|
+
config.voiceProviderKeys = config.voiceProviderKeys ?? {};
|
|
925
|
+
config.voiceProviderKeys.grok = env.XAI_API_KEY;
|
|
926
|
+
}
|
|
927
|
+
if (env.AGENTICMAIL_VOICE_RUNTIME && env.AGENTICMAIL_VOICE_RUNTIME.trim()) {
|
|
928
|
+
config.voiceRuntime = env.AGENTICMAIL_VOICE_RUNTIME.trim();
|
|
929
|
+
}
|
|
923
930
|
const configPath = join(config.dataDir, "config.json");
|
|
924
931
|
if (existsSync(configPath)) {
|
|
925
932
|
try {
|
|
@@ -7009,6 +7016,73 @@ var PhoneManager = class {
|
|
|
7009
7016
|
}]);
|
|
7010
7017
|
return { mission: updated, query: answered, alreadyAnswered: false };
|
|
7011
7018
|
}
|
|
7019
|
+
/**
|
|
7020
|
+
* v0.9.92 — auto-close stale operator queries.
|
|
7021
|
+
*
|
|
7022
|
+
* An operator query is "stale" when:
|
|
7023
|
+
* - it's unanswered, AND
|
|
7024
|
+
* - either (a) the mission is no longer live (status in
|
|
7025
|
+
* {completed, failed, cancelled}), OR (b) the query is older
|
|
7026
|
+
* than `maxAgeSeconds`.
|
|
7027
|
+
*
|
|
7028
|
+
* The sweeper marks each stale query as answered with a synthetic
|
|
7029
|
+
* "[auto-closed: ...]" answer + `answeredVia: 'auto-sweeper'`. This
|
|
7030
|
+
* (a) gets the query out of `listOpenOperatorQueries`, (b) clears
|
|
7031
|
+
* the bridge's "you have N open questions" hint to the operator,
|
|
7032
|
+
* and (c) leaves a permanent audit trail of WHY the query was
|
|
7033
|
+
* closed.
|
|
7034
|
+
*
|
|
7035
|
+
* Returns the count of queries closed + a per-mission breakdown
|
|
7036
|
+
* for logging.
|
|
7037
|
+
*/
|
|
7038
|
+
sweepStaleOperatorQueries(opts = {}) {
|
|
7039
|
+
const maxAgeMs = (opts.maxAgeSeconds ?? 3600) * 1e3;
|
|
7040
|
+
const nowMs = opts.nowMs ?? Date.now();
|
|
7041
|
+
const TERMINAL = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
7042
|
+
const rows = this.db.prepare(
|
|
7043
|
+
`SELECT * FROM phone_missions WHERE metadata_json LIKE '%"operatorQueries"%'`
|
|
7044
|
+
).all();
|
|
7045
|
+
const breakdown = [];
|
|
7046
|
+
let totalClosed = 0;
|
|
7047
|
+
let missionsTouched = 0;
|
|
7048
|
+
for (const row of rows) {
|
|
7049
|
+
const mission = rowToMission(row);
|
|
7050
|
+
const queries = readOperatorQueries(mission);
|
|
7051
|
+
const open = queries.filter((q) => !q.answer);
|
|
7052
|
+
if (open.length === 0) continue;
|
|
7053
|
+
const reason = TERMINAL.has(mission.status) ? "mission-terminal" : null;
|
|
7054
|
+
const closedAt = new Date(nowMs).toISOString();
|
|
7055
|
+
const nextQueries = queries.map((q) => {
|
|
7056
|
+
if (q.answer) return q;
|
|
7057
|
+
const askedAtMs = Date.parse(q.askedAt);
|
|
7058
|
+
const tooOld = Number.isFinite(askedAtMs) && nowMs - askedAtMs >= maxAgeMs;
|
|
7059
|
+
const queryReason = reason ?? (tooOld ? "age" : null);
|
|
7060
|
+
if (!queryReason) return q;
|
|
7061
|
+
return {
|
|
7062
|
+
...q,
|
|
7063
|
+
answer: queryReason === "mission-terminal" ? `[auto-closed: mission ended (${mission.status}) before this question was answered]` : `[auto-closed: question went unanswered for over ${Math.round(maxAgeMs / 6e4)} minutes]`,
|
|
7064
|
+
answeredAt: closedAt,
|
|
7065
|
+
answeredVia: "auto-sweeper"
|
|
7066
|
+
};
|
|
7067
|
+
});
|
|
7068
|
+
const closedHere = nextQueries.filter(
|
|
7069
|
+
(q, i) => q.answer && !queries[i].answer && q.answeredVia === "auto-sweeper"
|
|
7070
|
+
).length;
|
|
7071
|
+
if (closedHere === 0) continue;
|
|
7072
|
+
this.updateMissionStatus(mission.id, mission.status, {
|
|
7073
|
+
operatorQueries: nextQueries
|
|
7074
|
+
}, [{
|
|
7075
|
+
at: closedAt,
|
|
7076
|
+
source: "system",
|
|
7077
|
+
text: `Auto-closed ${closedHere} stale operator query(ies): ${reason ?? "aged out"}.`,
|
|
7078
|
+
metadata: { closedCount: closedHere, reason: reason ?? "age" }
|
|
7079
|
+
}]);
|
|
7080
|
+
totalClosed += closedHere;
|
|
7081
|
+
missionsTouched += 1;
|
|
7082
|
+
breakdown.push({ missionId: mission.id, closed: closedHere, reason: reason ?? "age" });
|
|
7083
|
+
}
|
|
7084
|
+
return { closed: totalClosed, missionsTouched, breakdown };
|
|
7085
|
+
}
|
|
7012
7086
|
// ─── Callback on disconnect (plan §7) ─────────────────
|
|
7013
7087
|
/**
|
|
7014
7088
|
* Flag a mission for callback-on-disconnect: the call dropped while
|
|
@@ -9021,7 +9095,7 @@ var SEARCH_EMAIL_TOOL = {
|
|
|
9021
9095
|
var SEARCH_SKILLS_TOOL = {
|
|
9022
9096
|
type: "function",
|
|
9023
9097
|
name: "search_skills",
|
|
9024
|
-
description:
|
|
9098
|
+
description: 'Search your skill library for a playbook that fits the situation you just hit on this call (billing dispute, debt collector tactics, reservation deadlock, etc). Returns up to 5 ranked matches, each with: id, name, BM25 score, when_to_use (the specific situation the skill is for), first_principle (the playbook\'s strategic frame), and a `recommendation` field. If `recommendation` says LOAD IT NOW or the top score > 0.3, immediately call load_skill with the top id \u2014 do not deliberate. If scores are weak (< 0.15), re-search with a different phrasing instead of loading a poor match. The model that judges "is this the right skill" is YOU \u2014 but the recommendation field will tell you what the right move usually is.',
|
|
9025
9099
|
parameters: {
|
|
9026
9100
|
type: "object",
|
|
9027
9101
|
properties: {
|
|
@@ -9676,7 +9750,7 @@ var RealtimeVoiceBridge = class {
|
|
|
9676
9750
|
let loadSkill2;
|
|
9677
9751
|
let renderSkillAsPrompt2;
|
|
9678
9752
|
try {
|
|
9679
|
-
({ loadSkill: loadSkill2, renderSkillAsPrompt: renderSkillAsPrompt2 } = await import("./skills-
|
|
9753
|
+
({ loadSkill: loadSkill2, renderSkillAsPrompt: renderSkillAsPrompt2 } = await import("./skills-DZVDIMTD.js"));
|
|
9680
9754
|
} catch (err) {
|
|
9681
9755
|
return { ok: false, message: `Skill registry unavailable: ${errorText(err)}` };
|
|
9682
9756
|
}
|
|
@@ -10463,6 +10537,94 @@ function withTimeout(promise, ms) {
|
|
|
10463
10537
|
return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));
|
|
10464
10538
|
}
|
|
10465
10539
|
|
|
10540
|
+
// src/phone/voice-providers/registry.ts
|
|
10541
|
+
var PROVIDERS2 = /* @__PURE__ */ new Map();
|
|
10542
|
+
function registerVoiceProvider(provider) {
|
|
10543
|
+
if (PROVIDERS2.has(provider.id)) {
|
|
10544
|
+
throw new Error(`Voice provider "${provider.id}" registered twice \u2014 id collision.`);
|
|
10545
|
+
}
|
|
10546
|
+
PROVIDERS2.set(provider.id, provider);
|
|
10547
|
+
}
|
|
10548
|
+
function listVoiceProviders() {
|
|
10549
|
+
return Array.from(PROVIDERS2.values());
|
|
10550
|
+
}
|
|
10551
|
+
function getVoiceProvider(id) {
|
|
10552
|
+
return PROVIDERS2.get(id);
|
|
10553
|
+
}
|
|
10554
|
+
function resolveVoiceRuntime(providerId, config, options = {}) {
|
|
10555
|
+
const id = (providerId || "openai").trim() || "openai";
|
|
10556
|
+
const provider = PROVIDERS2.get(id);
|
|
10557
|
+
if (!provider) {
|
|
10558
|
+
const known = Array.from(PROVIDERS2.keys()).join(", ") || "(none registered)";
|
|
10559
|
+
throw new Error(
|
|
10560
|
+
`Unknown voice runtime "${id}". Known providers: ${known}. Add a new one by dropping a file into packages/core/src/phone/voice-providers/.`
|
|
10561
|
+
);
|
|
10562
|
+
}
|
|
10563
|
+
let apiKey = "";
|
|
10564
|
+
let apiKeySource = "";
|
|
10565
|
+
if (provider.apiKeyConfigField) {
|
|
10566
|
+
const legacy = config[provider.apiKeyConfigField];
|
|
10567
|
+
if (legacy && legacy.trim()) {
|
|
10568
|
+
apiKey = legacy.trim();
|
|
10569
|
+
apiKeySource = `config.${provider.apiKeyConfigField}`;
|
|
10570
|
+
}
|
|
10571
|
+
}
|
|
10572
|
+
if (!apiKey) {
|
|
10573
|
+
const fromMap = config.voiceProviderKeys?.[provider.id];
|
|
10574
|
+
if (fromMap && fromMap.trim()) {
|
|
10575
|
+
apiKey = fromMap.trim();
|
|
10576
|
+
apiKeySource = `config.voiceProviderKeys.${provider.id}`;
|
|
10577
|
+
}
|
|
10578
|
+
}
|
|
10579
|
+
if (!apiKey) {
|
|
10580
|
+
const fromEnv = process.env[provider.apiKeyEnvVar];
|
|
10581
|
+
if (fromEnv && fromEnv.trim()) {
|
|
10582
|
+
apiKey = fromEnv.trim();
|
|
10583
|
+
apiKeySource = `env ${provider.apiKeyEnvVar}`;
|
|
10584
|
+
}
|
|
10585
|
+
}
|
|
10586
|
+
if (!apiKey) {
|
|
10587
|
+
throw new Error(
|
|
10588
|
+
`Voice provider "${provider.id}" (${provider.displayName}) selected, but no API key is configured. Set ${provider.apiKeyEnvVar} in your environment or save it to ~/.agenticmail/config.json under voiceProviderKeys.${provider.id}.`
|
|
10589
|
+
);
|
|
10590
|
+
}
|
|
10591
|
+
const model = options.model && options.model.trim() || provider.defaultModel;
|
|
10592
|
+
const url = `${provider.websocketBaseUrl}?model=${encodeURIComponent(model)}`;
|
|
10593
|
+
return {
|
|
10594
|
+
providerId: provider.id,
|
|
10595
|
+
providerDisplayName: provider.displayName,
|
|
10596
|
+
url,
|
|
10597
|
+
model,
|
|
10598
|
+
apiKey,
|
|
10599
|
+
apiKeySource
|
|
10600
|
+
};
|
|
10601
|
+
}
|
|
10602
|
+
|
|
10603
|
+
// src/phone/voice-providers/openai.ts
|
|
10604
|
+
registerVoiceProvider({
|
|
10605
|
+
id: "openai",
|
|
10606
|
+
displayName: "OpenAI Realtime (gpt-realtime)",
|
|
10607
|
+
websocketBaseUrl: "wss://api.openai.com/v1/realtime",
|
|
10608
|
+
defaultModel: "gpt-realtime",
|
|
10609
|
+
apiKeyEnvVar: "OPENAI_API_KEY",
|
|
10610
|
+
// Legacy: the original config.json schema used a dedicated
|
|
10611
|
+
// `openaiApiKey` field for this key. The resolver checks that field
|
|
10612
|
+
// before the generic voiceProviderKeys map so existing installs
|
|
10613
|
+
// continue to work without migration.
|
|
10614
|
+
apiKeyConfigField: "openaiApiKey",
|
|
10615
|
+
description: "OpenAI Realtime (gpt-realtime). Default voice runtime; supports linear PCM @ 24 kHz (46elks) and G.711 \xB5-law @ 8 kHz (Twilio) without transcoding."
|
|
10616
|
+
});
|
|
10617
|
+
|
|
10618
|
+
// src/phone/voice-providers/grok.ts
|
|
10619
|
+
registerVoiceProvider({
|
|
10620
|
+
id: "grok",
|
|
10621
|
+
displayName: "xAI Grok Voice Agent",
|
|
10622
|
+
websocketBaseUrl: "wss://api.x.ai/v1/realtime",
|
|
10623
|
+
defaultModel: "grok-voice-latest",
|
|
10624
|
+
apiKeyEnvVar: "XAI_API_KEY",
|
|
10625
|
+
description: 'xAI Grok Voice Agent \u2014 OpenAI-Realtime-compatible WebSocket protocol; select via mission policy.voiceRuntime="grok" or env AGENTICMAIL_VOICE_RUNTIME=grok.'
|
|
10626
|
+
});
|
|
10627
|
+
|
|
10466
10628
|
// src/telemetry.ts
|
|
10467
10629
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
10468
10630
|
import { readFileSync as readFileSync2, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync3 } from "fs";
|
|
@@ -14792,6 +14954,7 @@ export {
|
|
|
14792
14954
|
getTelegramMe,
|
|
14793
14955
|
getTelegramUpdates,
|
|
14794
14956
|
getTelegramWebhookInfo,
|
|
14957
|
+
getVoiceProvider,
|
|
14795
14958
|
hostSessionStoragePath,
|
|
14796
14959
|
inferPhoneRegion,
|
|
14797
14960
|
invalidateSkillCache,
|
|
@@ -14804,6 +14967,7 @@ export {
|
|
|
14804
14967
|
isTelegramStopCommand,
|
|
14805
14968
|
isValidPhoneNumber,
|
|
14806
14969
|
listSkills,
|
|
14970
|
+
listVoiceProviders,
|
|
14807
14971
|
loadAgentPersona,
|
|
14808
14972
|
loadHostSession,
|
|
14809
14973
|
loadSkill,
|
|
@@ -14832,6 +14996,7 @@ export {
|
|
|
14832
14996
|
redactSecret,
|
|
14833
14997
|
redactSmsConfig,
|
|
14834
14998
|
redactTelegramConfig,
|
|
14999
|
+
registerVoiceProvider,
|
|
14835
15000
|
renderSkillAsPrompt,
|
|
14836
15001
|
requireBinary,
|
|
14837
15002
|
requireWhisperModel,
|
|
@@ -14839,6 +15004,7 @@ export {
|
|
|
14839
15004
|
resolveConfig,
|
|
14840
15005
|
resolveExtensionPolicy,
|
|
14841
15006
|
resolveTlsRejectUnauthorized,
|
|
15007
|
+
resolveVoiceRuntime,
|
|
14842
15008
|
safeJoin,
|
|
14843
15009
|
sanitizeEmail,
|
|
14844
15010
|
saveAgentPersona,
|