@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 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>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.520",
3
+ "version": "0.0.22-beta.521",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",