@voicelayer/sdk 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/brain/index.d.ts +2 -2
- package/dist/brain/index.js +52 -0
- package/dist/index.d.ts +314 -297
- package/dist/index.js +401 -195
- package/dist/runtime/text-session.d.ts +1 -1
- package/dist/runtime/text-session.js +155 -3
- package/dist/{text-session-Bf4Jni7H.d.ts → text-session-BbG3VG50.d.ts} +153 -122
- package/package.json +5 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { b0 as
|
|
1
|
+
export { b0 as EmailResolver, b1 as FlowResolver, b2 as GraphResolvers, b3 as GraphTraceEvent, b4 as KnowledgeResolver, b5 as LiveTextConversation, b6 as LiveTurnResult, b7 as PlaybookLibraryEntry, b8 as PlaybookResolver, b9 as RegistryToolsResolver, ba as RunLiveTextOptions, af as RunTextSessionOptions, ag as RunTextTranscriptOptions, ax as TextSession, ay as TextTranscriptResult, o as ToolExecutor, bb as dedupeConversationEmails, bc as denyPrivateNetwork, bd as privateNetworkOptInHonoured, be as runLiveTextConversation, aY as runTextSession, aZ as runTextTranscript, bf as runWithOpenAIScope, bg as toPlaybookResolution } from '../text-session-BbG3VG50.js';
|
|
2
2
|
import '@livekit/agents';
|
|
3
3
|
import 'zod';
|
|
4
4
|
import '../types-KqrAfY85.js';
|
|
@@ -9,8 +9,8 @@ import https from 'https';
|
|
|
9
9
|
import { Readable } from 'stream';
|
|
10
10
|
import { lookup } from 'dns/promises';
|
|
11
11
|
import 'quickjs-emscripten';
|
|
12
|
+
import { createHash, randomUUID } from 'crypto';
|
|
12
13
|
import { setup, createActor } from 'xstate';
|
|
13
|
-
import { randomUUID } from 'crypto';
|
|
14
14
|
|
|
15
15
|
var __defProp = Object.defineProperty;
|
|
16
16
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -238,6 +238,8 @@ var init_flow = __esm({
|
|
|
238
238
|
"ask",
|
|
239
239
|
"confirm",
|
|
240
240
|
"tool",
|
|
241
|
+
// Send an email through the workspace's email (metered, wallet-gated; From on a verified domain) — burn-down G-22.
|
|
242
|
+
"email",
|
|
241
243
|
"decision",
|
|
242
244
|
"handoff",
|
|
243
245
|
"end",
|
|
@@ -1255,6 +1257,61 @@ var init_forms = __esm({
|
|
|
1255
1257
|
"../contracts/src/forms.ts"() {
|
|
1256
1258
|
}
|
|
1257
1259
|
});
|
|
1260
|
+
function isEmailAddress(value) {
|
|
1261
|
+
return EMAIL_RE.test(value) && value.length <= 254;
|
|
1262
|
+
}
|
|
1263
|
+
function normalizeDomain(input) {
|
|
1264
|
+
return input.trim().toLowerCase().replace(/^[a-z]+:\/\//, "").replace(/\/.*$/, "").replace(/\.$/, "");
|
|
1265
|
+
}
|
|
1266
|
+
function isDomainName(value) {
|
|
1267
|
+
return DOMAIN_RE.test(value);
|
|
1268
|
+
}
|
|
1269
|
+
var EMAIL_RE, EMAIL_SUBJECT_MAX, EMAIL_TEXT_MAX, EMAIL_HTML_MAX, address, DOMAIN_RE, EmailDomainStatus, EmailDnsRecord;
|
|
1270
|
+
var init_email = __esm({
|
|
1271
|
+
"../contracts/src/email.ts"() {
|
|
1272
|
+
EMAIL_RE = /^[^\s@<>"]+@[^\s@<>"]+\.[^\s@<>"]+$/;
|
|
1273
|
+
EMAIL_SUBJECT_MAX = 200;
|
|
1274
|
+
EMAIL_TEXT_MAX = 5e4;
|
|
1275
|
+
EMAIL_HTML_MAX = 2e5;
|
|
1276
|
+
address = z.string().max(254).refine(isEmailAddress, { message: "must be an email address" });
|
|
1277
|
+
z.object({
|
|
1278
|
+
to: address,
|
|
1279
|
+
subject: z.string().min(1).max(EMAIL_SUBJECT_MAX),
|
|
1280
|
+
text: z.string().min(1).max(EMAIL_TEXT_MAX),
|
|
1281
|
+
html: z.string().min(1).max(EMAIL_HTML_MAX).optional(),
|
|
1282
|
+
// An address on one of the workspace's verified sending domains; omitted → the platform sender.
|
|
1283
|
+
from: address.optional(),
|
|
1284
|
+
// The display name shown beside `from` (or beside the platform sender's address).
|
|
1285
|
+
fromName: z.string().trim().min(1).max(64).refine((v) => !/[\r\n<>"]/.test(v), { message: 'must not contain line breaks, <, > or "' }).optional(),
|
|
1286
|
+
// Where a reply goes — any address; it needs no verification.
|
|
1287
|
+
replyTo: address.optional(),
|
|
1288
|
+
// The conversation (a call, a text conversation) the email belongs to — a conversation sends at most 3 emails.
|
|
1289
|
+
conversationId: z.string().min(1).max(128).optional()
|
|
1290
|
+
});
|
|
1291
|
+
DOMAIN_RE = /^(?=.{4,253}$)(?!-)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/;
|
|
1292
|
+
z.object({
|
|
1293
|
+
domain: z.string().max(253).transform(normalizeDomain).refine(isDomainName, { message: "must be a domain like example.com" })
|
|
1294
|
+
});
|
|
1295
|
+
EmailDomainStatus = z.enum(["pending", "verified", "failed"]);
|
|
1296
|
+
EmailDnsRecord = z.object({
|
|
1297
|
+
type: z.enum(["CNAME", "TXT"]),
|
|
1298
|
+
name: z.string(),
|
|
1299
|
+
value: z.string(),
|
|
1300
|
+
// dkim: proves the domain (required); dmarc: recommended, only when the domain has no DMARC record yet.
|
|
1301
|
+
purpose: z.enum(["dkim", "dmarc"]),
|
|
1302
|
+
required: z.boolean()
|
|
1303
|
+
});
|
|
1304
|
+
z.object({
|
|
1305
|
+
id: z.string(),
|
|
1306
|
+
domain: z.string(),
|
|
1307
|
+
status: EmailDomainStatus,
|
|
1308
|
+
records: z.array(EmailDnsRecord),
|
|
1309
|
+
createdAt: z.string().datetime(),
|
|
1310
|
+
lastCheckedAt: z.string().datetime().nullable(),
|
|
1311
|
+
verifiedAt: z.string().datetime().nullable()
|
|
1312
|
+
});
|
|
1313
|
+
}
|
|
1314
|
+
});
|
|
1258
1315
|
var AgentConfigVersionDTO, AgentConfigDiffField, AgentConfigChange;
|
|
1259
1316
|
var init_agent_versions = __esm({
|
|
1260
1317
|
"../contracts/src/agent-versions.ts"() {
|
|
@@ -2003,6 +2060,7 @@ var init_flow_validate = __esm({
|
|
|
2003
2060
|
init_secret_headers();
|
|
2004
2061
|
init_network_address();
|
|
2005
2062
|
init_dispatch_metadata();
|
|
2063
|
+
init_email();
|
|
2006
2064
|
init_flow_edges();
|
|
2007
2065
|
FlowIssueSeverity = z.enum(["error", "warning"]);
|
|
2008
2066
|
FlowIssue = z.object({
|
|
@@ -3776,6 +3834,7 @@ var init_src = __esm({
|
|
|
3776
3834
|
init_memory();
|
|
3777
3835
|
init_participants();
|
|
3778
3836
|
init_forms();
|
|
3837
|
+
init_email();
|
|
3779
3838
|
init_consultation();
|
|
3780
3839
|
init_agent_config();
|
|
3781
3840
|
init_agent_versions();
|
|
@@ -5228,7 +5287,7 @@ function menuDigitOf(b) {
|
|
|
5228
5287
|
function menuLabelOf(label) {
|
|
5229
5288
|
return label.replace(/^\s*[0-9*#]\s*[-—–:.]*\s*/, "").trim() || label.trim();
|
|
5230
5289
|
}
|
|
5231
|
-
var ASK_MAX_CLARIFY, COLLECT_MAX_STALLED_TURNS, LLM_MAX_TURNS, HUB_MAX_TURNS, NO_INPUT_MS, sayExecutor, YES_WORDS, NO_WORDS, confirmExecutor, askExecutor, gateExecutor, endExecutor, handoffExecutor, OPENING_SILENCE_MS, llmExecutor, toolExecutor, ragExecutor, codeExecutor, decisionExecutor, MENU_MAX_INPUTS, menuExecutor, classifyExecutor, routerExecutor, playbookExecutor, setExecutor, MAX_SUBFLOW_DEPTH, subflowExecutor, passthroughExecutor, EXECUTORS;
|
|
5290
|
+
var ASK_MAX_CLARIFY, COLLECT_MAX_STALLED_TURNS, LLM_MAX_TURNS, HUB_MAX_TURNS, NO_INPUT_MS, sayExecutor, YES_WORDS, NO_WORDS, confirmExecutor, askExecutor, gateExecutor, endExecutor, handoffExecutor, OPENING_SILENCE_MS, llmExecutor, toolExecutor, ragExecutor, codeExecutor, decisionExecutor, MENU_MAX_INPUTS, menuExecutor, classifyExecutor, routerExecutor, playbookExecutor, setExecutor, MAX_SUBFLOW_DEPTH, subflowExecutor, EmailStepTimeout, EMAIL_SEND_TIMEOUT_MS, emailExecutor, passthroughExecutor, EXECUTORS;
|
|
5232
5291
|
var init_executors = __esm({
|
|
5233
5292
|
"src/runtime/graph/executors.ts"() {
|
|
5234
5293
|
init_log();
|
|
@@ -6042,6 +6101,64 @@ ${collected}`);
|
|
|
6042
6101
|
if (outcome.kind === "handoff") return { kind: "handoff", to: outcome.to };
|
|
6043
6102
|
return { kind: "advance" };
|
|
6044
6103
|
};
|
|
6104
|
+
EmailStepTimeout = class extends Error {
|
|
6105
|
+
};
|
|
6106
|
+
EMAIL_SEND_TIMEOUT_MS = 1e4;
|
|
6107
|
+
emailExecutor = async (node, state, deps) => {
|
|
6108
|
+
const cfg = node.config;
|
|
6109
|
+
const scope2 = scopeFor(state, deps);
|
|
6110
|
+
const render = (key) => interpolate(str(cfg[key]), scope2).trim();
|
|
6111
|
+
const to = render("to");
|
|
6112
|
+
const from = render("from");
|
|
6113
|
+
const fromName = render("fromName");
|
|
6114
|
+
const replyTo = render("replyTo");
|
|
6115
|
+
const fail = (error, detail) => {
|
|
6116
|
+
state.nodeResults[node.id] = { ok: false, error, ...detail ? { detail } : {} };
|
|
6117
|
+
deps.events.note("email.failed", { node: node.id, error, ...detail ? { detail } : {} });
|
|
6118
|
+
return routeByPort(node, deps, "fail");
|
|
6119
|
+
};
|
|
6120
|
+
if (!isEmailAddress(to)) return fail("invalid_to", to ? "the recipient is not an email address" : "no recipient was captured");
|
|
6121
|
+
const resolver = deps.resolvers?.email;
|
|
6122
|
+
if (!resolver) {
|
|
6123
|
+
return fail(
|
|
6124
|
+
"email_unavailable",
|
|
6125
|
+
"email isn't sent here: a dry run, or a pool worker that couldn't get this call's workspace identity (worker token)"
|
|
6126
|
+
);
|
|
6127
|
+
}
|
|
6128
|
+
deps.events.note("email.sending", { node: node.id });
|
|
6129
|
+
const abort = new AbortController();
|
|
6130
|
+
let timer;
|
|
6131
|
+
try {
|
|
6132
|
+
const result = await Promise.race([
|
|
6133
|
+
resolver(
|
|
6134
|
+
{
|
|
6135
|
+
to,
|
|
6136
|
+
subject: render("subject"),
|
|
6137
|
+
text: interpolate(str(cfg.body), scope2),
|
|
6138
|
+
...from ? { from } : {},
|
|
6139
|
+
...fromName ? { fromName } : {},
|
|
6140
|
+
...replyTo ? { replyTo } : {}
|
|
6141
|
+
},
|
|
6142
|
+
{ signal: abort.signal }
|
|
6143
|
+
),
|
|
6144
|
+
new Promise((_, reject) => {
|
|
6145
|
+
timer = setTimeout(() => {
|
|
6146
|
+
abort.abort();
|
|
6147
|
+
reject(new EmailStepTimeout());
|
|
6148
|
+
}, EMAIL_SEND_TIMEOUT_MS);
|
|
6149
|
+
})
|
|
6150
|
+
]);
|
|
6151
|
+
if (!result.ok) return fail(result.error, result.detail);
|
|
6152
|
+
state.nodeResults[node.id] = { ok: true, emailId: result.emailId };
|
|
6153
|
+
deps.events.note("email.sent", { node: node.id, emailId: result.emailId });
|
|
6154
|
+
return routeByPort(node, deps, "ok");
|
|
6155
|
+
} catch (err) {
|
|
6156
|
+
if (err instanceof EmailStepTimeout) return fail("email_outcome_unknown", `no answer in ${EMAIL_SEND_TIMEOUT_MS} ms`);
|
|
6157
|
+
return fail("email_send_failed", err instanceof Error ? err.message : String(err));
|
|
6158
|
+
} finally {
|
|
6159
|
+
if (timer) clearTimeout(timer);
|
|
6160
|
+
}
|
|
6161
|
+
};
|
|
6045
6162
|
passthroughExecutor = async () => ({
|
|
6046
6163
|
kind: "advance"
|
|
6047
6164
|
});
|
|
@@ -6054,6 +6171,7 @@ ${collected}`);
|
|
|
6054
6171
|
handoff: handoffExecutor,
|
|
6055
6172
|
llm: llmExecutor,
|
|
6056
6173
|
tool: toolExecutor,
|
|
6174
|
+
email: emailExecutor,
|
|
6057
6175
|
set: setExecutor,
|
|
6058
6176
|
subflow: subflowExecutor,
|
|
6059
6177
|
decision: decisionExecutor,
|
|
@@ -6716,6 +6834,40 @@ init_graph_model();
|
|
|
6716
6834
|
init_src();
|
|
6717
6835
|
init_embedder();
|
|
6718
6836
|
init_llm();
|
|
6837
|
+
z.object({
|
|
6838
|
+
emailId: z.string()
|
|
6839
|
+
}).passthrough();
|
|
6840
|
+
|
|
6841
|
+
// src/runtime/graph/resolvers.ts
|
|
6842
|
+
var NOT_SENT = /* @__PURE__ */ new Set([
|
|
6843
|
+
"invalid_email",
|
|
6844
|
+
"invalid_body",
|
|
6845
|
+
"from_not_verified",
|
|
6846
|
+
"email_rate_limited",
|
|
6847
|
+
"email_conversation_limit",
|
|
6848
|
+
"email_unavailable",
|
|
6849
|
+
"email_provider_error",
|
|
6850
|
+
"email_send_failed",
|
|
6851
|
+
"insufficient_balance",
|
|
6852
|
+
"spend_cap_exceeded"
|
|
6853
|
+
]);
|
|
6854
|
+
function dedupeConversationEmails(resolver) {
|
|
6855
|
+
const sends = /* @__PURE__ */ new Map();
|
|
6856
|
+
return (req, opts) => {
|
|
6857
|
+
const body = createHash("sha256").update(req.text).digest("hex");
|
|
6858
|
+
const key = `${req.to.trim().toLowerCase()}
|
|
6859
|
+
${req.subject}
|
|
6860
|
+
${body}`;
|
|
6861
|
+
const prior = sends.get(key);
|
|
6862
|
+
if (prior) return prior;
|
|
6863
|
+
const sending = resolver(req, opts).then((result) => {
|
|
6864
|
+
if (!result.ok && NOT_SENT.has(result.error)) sends.delete(key);
|
|
6865
|
+
return result;
|
|
6866
|
+
});
|
|
6867
|
+
sends.set(key, sending);
|
|
6868
|
+
return sending;
|
|
6869
|
+
};
|
|
6870
|
+
}
|
|
6719
6871
|
function toPlaybookResolution(pb) {
|
|
6720
6872
|
const requiredFields = Array.from(
|
|
6721
6873
|
new Set((pb.exitConditions ?? []).flatMap((e) => e.requiredVariables ?? []))
|
|
@@ -8044,4 +8196,4 @@ function runLiveTextConversation(opts) {
|
|
|
8044
8196
|
};
|
|
8045
8197
|
}
|
|
8046
8198
|
|
|
8047
|
-
export { denyPrivateNetwork, privateNetworkOptInHonoured, runLiveTextConversation, runTextSession, runTextTranscript, runWithOpenAIScope, toPlaybookResolution };
|
|
8199
|
+
export { dedupeConversationEmails, denyPrivateNetwork, privateNetworkOptInHonoured, runLiveTextConversation, runTextSession, runTextTranscript, runWithOpenAIScope, toPlaybookResolution };
|