@absolutejs/voice 0.0.22-beta.520 → 0.0.22-beta.521
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/index.js +114 -0
- package/dist/pathwayGenerator.d.ts +27 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -353,6 +353,8 @@ export { compileVoicePathwayToAssistant } from "./pathwayCompiler";
|
|
|
353
353
|
export type { CompileVoicePathwayOptions, VoicePathwayCompiledAssistant, VoicePathwayCompilerToolDefinition, } from "./pathwayCompiler";
|
|
354
354
|
export { renderVoicePathwayMermaid, renderVoicePathwayText, visualizeVoicePathway, } from "./pathwayVisualizer";
|
|
355
355
|
export type { VoicePathwayVisualization } from "./pathwayVisualizer";
|
|
356
|
+
export { generateVoicePathwayFromPrompt } from "./pathwayGenerator";
|
|
357
|
+
export type { GenerateVoicePathwayInput, GenerateVoicePathwayResult, VoicePathwayGeneratorCompletion, } from "./pathwayGenerator";
|
|
356
358
|
export { createVoiceCRMRegistry } from "./crmContract";
|
|
357
359
|
export type { CreateVoiceCRMRegistryOptions, VoiceCRMCallActivityInput, VoiceCRMContactSummary, VoiceCRMContract, VoiceCRMLeadInput, VoiceCRMNoteInput, VoiceCRMRegistry, VoiceCRMTaskInput, } from "./crmContract";
|
|
358
360
|
export { createInMemoryVoiceCallerCRMLinkCache, createVoiceCallerCRMLinker, } from "./callerCRMLinker";
|
package/dist/index.js
CHANGED
|
@@ -51531,6 +51531,119 @@ var visualizeVoicePathway = (pathway) => ({
|
|
|
51531
51531
|
mermaid: renderVoicePathwayMermaid(pathway),
|
|
51532
51532
|
text: renderVoicePathwayText(pathway)
|
|
51533
51533
|
});
|
|
51534
|
+
// src/pathwayGenerator.ts
|
|
51535
|
+
var SYSTEM_PROMPT = `You design conversation pathways for voice agents as strict JSON.
|
|
51536
|
+
|
|
51537
|
+
A pathway is a state machine. Output ONLY a JSON object with this shape:
|
|
51538
|
+
{
|
|
51539
|
+
"id": "kebab-case-id",
|
|
51540
|
+
"label": "Human readable label",
|
|
51541
|
+
"entryStateId": "<id of the first state>",
|
|
51542
|
+
"slots": [
|
|
51543
|
+
{ "id": "slot_id", "type": "string|number|boolean|date|time|phone|email|currency|choice", "prompt": "what to ask", "required": true, "choices": ["a","b"] }
|
|
51544
|
+
],
|
|
51545
|
+
"states": [
|
|
51546
|
+
{
|
|
51547
|
+
"id": "state_id",
|
|
51548
|
+
"label": "Label",
|
|
51549
|
+
"kind": "entry|collect|branch|action|terminal",
|
|
51550
|
+
"actions": [
|
|
51551
|
+
{ "kind": "say", "text": "..." },
|
|
51552
|
+
{ "kind": "collect-slot", "slotId": "slot_id" },
|
|
51553
|
+
{ "kind": "call-tool", "toolId": "tool_id", "argsFromSlots": ["slot_id"] },
|
|
51554
|
+
{ "kind": "transfer", "destination": "..." },
|
|
51555
|
+
{ "kind": "end-call", "reason": "..." }
|
|
51556
|
+
],
|
|
51557
|
+
"transitions": [
|
|
51558
|
+
{ "to": "next_state", "condition": { "kind": "always" } },
|
|
51559
|
+
{ "to": "x", "condition": { "kind": "slot-filled", "slotId": "slot_id" } },
|
|
51560
|
+
{ "to": "y", "condition": { "kind": "slot-equals", "slotId": "slot_id", "value": "yes" } },
|
|
51561
|
+
{ "to": "z", "condition": { "kind": "fallback" } }
|
|
51562
|
+
]
|
|
51563
|
+
}
|
|
51564
|
+
],
|
|
51565
|
+
"tools": [ { "id": "tool_id", "description": "..." } ]
|
|
51566
|
+
}
|
|
51567
|
+
|
|
51568
|
+
Hard rules:
|
|
51569
|
+
- Exactly one entry state; entryStateId must reference a real state.
|
|
51570
|
+
- At least one terminal state (kind "terminal" or a state with no transitions) must be reachable from entry.
|
|
51571
|
+
- Every transition "to" must reference a defined state id.
|
|
51572
|
+
- Every slotId referenced in actions/conditions must be defined in "slots".
|
|
51573
|
+
- A "fallback" transition, if present, must be the LAST transition in its state.
|
|
51574
|
+
- Do not invent extra fields. Output JSON only \u2014 no prose, no markdown fences.`;
|
|
51575
|
+
var slugify = (value) => value.toLowerCase().trim().replace(/[^a-z0-9]+/gu, "-").replace(/^-+|-+$/gu, "").slice(0, 60) || "generated-pathway";
|
|
51576
|
+
var extractJson4 = (raw) => {
|
|
51577
|
+
const trimmed = raw.trim();
|
|
51578
|
+
if (!trimmed)
|
|
51579
|
+
throw new Error("Pathway generator returned an empty response");
|
|
51580
|
+
const fenced = /```(?:json)?\s*([\s\S]*?)```/iu.exec(trimmed);
|
|
51581
|
+
const candidate = fenced ? fenced[1].trim() : trimmed;
|
|
51582
|
+
try {
|
|
51583
|
+
return JSON.parse(candidate);
|
|
51584
|
+
} catch {
|
|
51585
|
+
const start = candidate.indexOf("{");
|
|
51586
|
+
const end = candidate.lastIndexOf("}");
|
|
51587
|
+
if (start >= 0 && end > start) {
|
|
51588
|
+
return JSON.parse(candidate.slice(start, end + 1));
|
|
51589
|
+
}
|
|
51590
|
+
throw new Error(`Pathway generator response was not valid JSON: ${raw.slice(0, 200)}`);
|
|
51591
|
+
}
|
|
51592
|
+
};
|
|
51593
|
+
var coercePathway = (parsed, fallbackId) => {
|
|
51594
|
+
if (!parsed || typeof parsed !== "object") {
|
|
51595
|
+
throw new Error("Pathway generator response is not a JSON object");
|
|
51596
|
+
}
|
|
51597
|
+
const root = parsed;
|
|
51598
|
+
return {
|
|
51599
|
+
entryStateId: String(root.entryStateId ?? ""),
|
|
51600
|
+
id: typeof root.id === "string" && root.id.length > 0 ? root.id : fallbackId,
|
|
51601
|
+
label: String(root.label ?? "Generated pathway"),
|
|
51602
|
+
slots: Array.isArray(root.slots) ? root.slots : [],
|
|
51603
|
+
states: Array.isArray(root.states) ? root.states : [],
|
|
51604
|
+
...Array.isArray(root.tools) ? { tools: root.tools } : {},
|
|
51605
|
+
...root.metadata && typeof root.metadata === "object" ? { metadata: root.metadata } : {}
|
|
51606
|
+
};
|
|
51607
|
+
};
|
|
51608
|
+
var generateVoicePathwayFromPrompt = async (input) => {
|
|
51609
|
+
const fallbackId = input.id ?? slugify(input.description);
|
|
51610
|
+
const maxRepairs = input.maxRepairAttempts ?? 2;
|
|
51611
|
+
const systemPrompt = input.guidance ? `${SYSTEM_PROMPT}
|
|
51612
|
+
|
|
51613
|
+
Additional guidance:
|
|
51614
|
+
${input.guidance}` : SYSTEM_PROMPT;
|
|
51615
|
+
const rawOutputs = [];
|
|
51616
|
+
let lastReport = null;
|
|
51617
|
+
let lastPathway = null;
|
|
51618
|
+
for (let attempt = 0;attempt <= maxRepairs; attempt += 1) {
|
|
51619
|
+
const prompt = attempt === 0 ? `Build a voice pathway for:
|
|
51620
|
+
${input.description}
|
|
51621
|
+
|
|
51622
|
+
Suggested id: ${fallbackId}` : `The previous pathway JSON failed validation with these errors:
|
|
51623
|
+
${lastReport.issues.filter((issue) => issue.severity === "error").map((issue) => `- ${issue.message}`).join(`
|
|
51624
|
+
`)}
|
|
51625
|
+
|
|
51626
|
+
Here was your previous output:
|
|
51627
|
+
${rawOutputs.at(-1)}
|
|
51628
|
+
|
|
51629
|
+
Return a corrected pathway JSON that fixes every error.`;
|
|
51630
|
+
const raw = await input.completion({ prompt, systemPrompt });
|
|
51631
|
+
rawOutputs.push(raw);
|
|
51632
|
+
const pathway = coercePathway(extractJson4(raw), fallbackId);
|
|
51633
|
+
const report = validateVoicePathway(pathway);
|
|
51634
|
+
lastReport = report;
|
|
51635
|
+
lastPathway = pathway;
|
|
51636
|
+
if (report.valid) {
|
|
51637
|
+
return { attempts: attempt + 1, pathway, rawOutputs, report };
|
|
51638
|
+
}
|
|
51639
|
+
}
|
|
51640
|
+
return {
|
|
51641
|
+
attempts: rawOutputs.length,
|
|
51642
|
+
pathway: lastPathway,
|
|
51643
|
+
rawOutputs,
|
|
51644
|
+
report: lastReport
|
|
51645
|
+
};
|
|
51646
|
+
};
|
|
51534
51647
|
// src/crmContract.ts
|
|
51535
51648
|
var createVoiceCRMRegistry = (options) => {
|
|
51536
51649
|
const byVendor = new Map;
|
|
@@ -51970,6 +52083,7 @@ export {
|
|
|
51970
52083
|
getLatestVoiceTelephonyMediaReport,
|
|
51971
52084
|
getLatestVoiceBrowserMediaReport,
|
|
51972
52085
|
getDefaultVoiceTelephonyBenchmarkScenarios,
|
|
52086
|
+
generateVoicePathwayFromPrompt,
|
|
51973
52087
|
generateVoiceCalendarSlots,
|
|
51974
52088
|
fromVapiAssistantConfig,
|
|
51975
52089
|
formatVoiceProofTrendAge,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type VoicePathway, type VoicePathwayValidationReport } from "./pathway";
|
|
2
|
+
export type VoicePathwayGeneratorCompletion = (input: {
|
|
3
|
+
prompt: string;
|
|
4
|
+
systemPrompt: string;
|
|
5
|
+
}) => Promise<string>;
|
|
6
|
+
export type GenerateVoicePathwayInput = {
|
|
7
|
+
/** Plain-text description of the agent / flow to build. */
|
|
8
|
+
description: string;
|
|
9
|
+
completion: VoicePathwayGeneratorCompletion;
|
|
10
|
+
/** Suggested pathway id (slugified). Defaults to "generated-pathway". */
|
|
11
|
+
id?: string;
|
|
12
|
+
/** Extra guidance appended to the system prompt. */
|
|
13
|
+
guidance?: string;
|
|
14
|
+
/**
|
|
15
|
+
* If the first attempt fails validation, retry this many times feeding the
|
|
16
|
+
* issues back to the model. Defaults to 2.
|
|
17
|
+
*/
|
|
18
|
+
maxRepairAttempts?: number;
|
|
19
|
+
};
|
|
20
|
+
export type GenerateVoicePathwayResult = {
|
|
21
|
+
pathway: VoicePathway;
|
|
22
|
+
report: VoicePathwayValidationReport;
|
|
23
|
+
attempts: number;
|
|
24
|
+
/** Raw model outputs from each attempt, for debugging. */
|
|
25
|
+
rawOutputs: string[];
|
|
26
|
+
};
|
|
27
|
+
export declare const generateVoicePathwayFromPrompt: (input: GenerateVoicePathwayInput) => Promise<GenerateVoicePathwayResult>;
|