@diegoaltoworks/talker 0.1.0

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.
Files changed (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +299 -0
  3. package/dist/adapters/twilio.d.ts +12 -0
  4. package/dist/adapters/twilio.d.ts.map +1 -0
  5. package/dist/core/chat.d.ts +14 -0
  6. package/dist/core/chat.d.ts.map +1 -0
  7. package/dist/core/chatbot/client.d.ts +12 -0
  8. package/dist/core/chatbot/client.d.ts.map +1 -0
  9. package/dist/core/chatbot/conversations.d.ts +14 -0
  10. package/dist/core/chatbot/conversations.d.ts.map +1 -0
  11. package/dist/core/chatbot/index.d.ts +9 -0
  12. package/dist/core/chatbot/index.d.ts.map +1 -0
  13. package/dist/core/chatbot/types.d.ts +25 -0
  14. package/dist/core/chatbot/types.d.ts.map +1 -0
  15. package/dist/core/context.d.ts +61 -0
  16. package/dist/core/context.d.ts.map +1 -0
  17. package/dist/core/context.test.d.ts +2 -0
  18. package/dist/core/context.test.d.ts.map +1 -0
  19. package/dist/core/errors.d.ts +8 -0
  20. package/dist/core/errors.d.ts.map +1 -0
  21. package/dist/core/errors.test.d.ts +2 -0
  22. package/dist/core/errors.test.d.ts.map +1 -0
  23. package/dist/core/logger.d.ts +11 -0
  24. package/dist/core/logger.d.ts.map +1 -0
  25. package/dist/core/phrases.d.ts +30 -0
  26. package/dist/core/phrases.d.ts.map +1 -0
  27. package/dist/core/phrases.test.d.ts +2 -0
  28. package/dist/core/phrases.test.d.ts.map +1 -0
  29. package/dist/core/processing/incoming.d.ts +12 -0
  30. package/dist/core/processing/incoming.d.ts.map +1 -0
  31. package/dist/core/processing/index.d.ts +10 -0
  32. package/dist/core/processing/index.d.ts.map +1 -0
  33. package/dist/core/processing/openai.d.ts +15 -0
  34. package/dist/core/processing/openai.d.ts.map +1 -0
  35. package/dist/core/processing/outgoing.d.ts +12 -0
  36. package/dist/core/processing/outgoing.d.ts.map +1 -0
  37. package/dist/core/processing/prompts.d.ts +14 -0
  38. package/dist/core/processing/prompts.d.ts.map +1 -0
  39. package/dist/core/twiml.d.ts +31 -0
  40. package/dist/core/twiml.d.ts.map +1 -0
  41. package/dist/core/twiml.test.d.ts +2 -0
  42. package/dist/core/twiml.test.d.ts.map +1 -0
  43. package/dist/core/voice.d.ts +16 -0
  44. package/dist/core/voice.d.ts.map +1 -0
  45. package/dist/core/voice.test.d.ts +2 -0
  46. package/dist/core/voice.test.d.ts.map +1 -0
  47. package/dist/core/xml.d.ts +8 -0
  48. package/dist/core/xml.d.ts.map +1 -0
  49. package/dist/core/xml.test.d.ts +2 -0
  50. package/dist/core/xml.test.d.ts.map +1 -0
  51. package/dist/db/client.d.ts +25 -0
  52. package/dist/db/client.d.ts.map +1 -0
  53. package/dist/db/index.d.ts +12 -0
  54. package/dist/db/index.d.ts.map +1 -0
  55. package/dist/db/migrate.d.ts +8 -0
  56. package/dist/db/migrate.d.ts.map +1 -0
  57. package/dist/db/persist.d.ts +18 -0
  58. package/dist/db/persist.d.ts.map +1 -0
  59. package/dist/db/sessions.d.ts +57 -0
  60. package/dist/db/sessions.d.ts.map +1 -0
  61. package/dist/flows/index.d.ts +12 -0
  62. package/dist/flows/index.d.ts.map +1 -0
  63. package/dist/flows/intent.d.ts +11 -0
  64. package/dist/flows/intent.d.ts.map +1 -0
  65. package/dist/flows/loader.d.ts +12 -0
  66. package/dist/flows/loader.d.ts.map +1 -0
  67. package/dist/flows/manager.d.ts +14 -0
  68. package/dist/flows/manager.d.ts.map +1 -0
  69. package/dist/flows/params.d.ts +12 -0
  70. package/dist/flows/params.d.ts.map +1 -0
  71. package/dist/flows/registry.d.ts +35 -0
  72. package/dist/flows/registry.d.ts.map +1 -0
  73. package/dist/flows/utils.d.ts +12 -0
  74. package/dist/flows/utils.d.ts.map +1 -0
  75. package/dist/flows/utils.test.d.ts +2 -0
  76. package/dist/flows/utils.test.d.ts.map +1 -0
  77. package/dist/index.d.ts +62 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +1840 -0
  80. package/dist/index.mjs +1771 -0
  81. package/dist/plugin.d.ts +31 -0
  82. package/dist/plugin.d.ts.map +1 -0
  83. package/dist/routes/call/handle-answer.d.ts +10 -0
  84. package/dist/routes/call/handle-answer.d.ts.map +1 -0
  85. package/dist/routes/call/handle-initial.d.ts +10 -0
  86. package/dist/routes/call/handle-initial.d.ts.map +1 -0
  87. package/dist/routes/call/handle-nospeech.d.ts +10 -0
  88. package/dist/routes/call/handle-nospeech.d.ts.map +1 -0
  89. package/dist/routes/call/handle-respond.d.ts +11 -0
  90. package/dist/routes/call/handle-respond.d.ts.map +1 -0
  91. package/dist/routes/call/handle-status.d.ts +9 -0
  92. package/dist/routes/call/handle-status.d.ts.map +1 -0
  93. package/dist/routes/call/index.d.ts +14 -0
  94. package/dist/routes/call/index.d.ts.map +1 -0
  95. package/dist/routes/call/pending.d.ts +20 -0
  96. package/dist/routes/call/pending.d.ts.map +1 -0
  97. package/dist/routes/call/processor.d.ts +13 -0
  98. package/dist/routes/call/processor.d.ts.map +1 -0
  99. package/dist/routes/sms/handle-incoming.d.ts +10 -0
  100. package/dist/routes/sms/handle-incoming.d.ts.map +1 -0
  101. package/dist/routes/sms/index.d.ts +13 -0
  102. package/dist/routes/sms/index.d.ts.map +1 -0
  103. package/dist/routes/sms/processor.d.ts +12 -0
  104. package/dist/routes/sms/processor.d.ts.map +1 -0
  105. package/dist/standalone.d.ts +44 -0
  106. package/dist/standalone.d.ts.map +1 -0
  107. package/dist/types.d.ts +240 -0
  108. package/dist/types.d.ts.map +1 -0
  109. package/language/de.json +27 -0
  110. package/language/en.json +27 -0
  111. package/language/es.json +27 -0
  112. package/language/fr.json +27 -0
  113. package/language/nl.json +27 -0
  114. package/language/pt.json +27 -0
  115. package/package.json +103 -0
  116. package/prompts/incoming.md +88 -0
  117. package/prompts/outgoing.md +58 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Diego Alto
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,299 @@
1
+ # Talker
2
+
3
+ <div align="center">
4
+
5
+ **Telephony plugin for Chatter — voice call and SMS support via Twilio**
6
+
7
+ [![NPM Version](https://img.shields.io/npm/v/@diegoaltoworks/talker)](https://www.npmjs.com/package/@diegoaltoworks/talker)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+
10
+ [Features](#features) • [Quick Start](#quick-start) • [Examples](#examples) • [Configuration](#configuration) • [Customization](#customization)
11
+
12
+ </div>
13
+
14
+ ## Features
15
+
16
+ - **Voice Calls**: Twilio webhook handlers with speech-to-text, text-to-speech, and continuous conversation loops
17
+ - **SMS**: Inbound/outbound messaging with channel-appropriate formatting
18
+ - **Pre/Post-Processing**: OpenAI-powered language detection, STT artifact cleanup, phone-friendly response formatting, and automatic translation
19
+ - **Structured Flows**: LLM intent detection + parameter extraction for guided multi-step conversations
20
+ - **Human Handoff**: Automatic transfer to a real person on request or frustration signals
21
+ - **Multi-Language**: English, French, German, Dutch, Spanish, Portuguese out of the box
22
+ - **Two Modes**: Plugin for [Chatter](https://github.com/diegoaltoworks/chatter), or standalone with any chatbot backend
23
+ - **TypeScript**: Fully typed for excellent developer experience
24
+
25
+ ## Quick Start
26
+
27
+ ```bash
28
+ # With chatter (plugin mode)
29
+ bun add @diegoaltoworks/talker
30
+
31
+ # Standalone (no chatter required)
32
+ bun add @diegoaltoworks/talker hono
33
+ ```
34
+
35
+ **As a Chatter plugin** — one server, one port, web chat + phone + SMS:
36
+
37
+ ```typescript
38
+ import { createServer } from '@diegoaltoworks/chatter';
39
+ import { createTelephonyRoutes } from '@diegoaltoworks/talker';
40
+
41
+ const app = await createServer({
42
+ bot: { name: 'MyBot', personName: 'Your Name' },
43
+ openai: { apiKey: process.env.OPENAI_API_KEY },
44
+ database: { url: process.env.TURSO_URL, authToken: process.env.TURSO_AUTH_TOKEN },
45
+ customRoutes: async (app, deps) => {
46
+ await createTelephonyRoutes(app, deps, {
47
+ twilio: {
48
+ accountSid: process.env.TWILIO_ACCOUNT_SID,
49
+ authToken: process.env.TWILIO_AUTH_TOKEN,
50
+ phoneNumber: process.env.TWILIO_PHONE_NUMBER,
51
+ },
52
+ transferNumber: '+441234567890',
53
+ });
54
+ },
55
+ });
56
+
57
+ Bun.serve({ port: 8181, fetch: app.fetch });
58
+ ```
59
+
60
+ **As a standalone server** — point at a remote chatbot API:
61
+
62
+ ```typescript
63
+ import { createStandaloneServer } from '@diegoaltoworks/talker';
64
+
65
+ const app = await createStandaloneServer({
66
+ openaiApiKey: process.env.OPENAI_CHATGPT_KEY || '',
67
+ chatbot: {
68
+ url: process.env.CHATBOT_URL || 'http://localhost:8181/api/public/chat',
69
+ apiKey: process.env.CHATBOT_API_KEY,
70
+ },
71
+ transferNumber: '+441234567890',
72
+ });
73
+
74
+ Bun.serve({ port: 3000, fetch: app.fetch });
75
+ ```
76
+
77
+ **Requirements:** OpenAI API key, Bun runtime. Twilio account for production use.
78
+
79
+ ## Examples
80
+
81
+ **[Complete Examples](./examples/)** — Ready-to-run examples for all use cases:
82
+
83
+ - **[Chatter Plugin](./examples/chatter-plugin.ts)** — Single server with web chat + phone + SMS
84
+ - **[Standalone Server](./examples/standalone.ts)** — Phone/SMS with your own chatbot backend
85
+ - **[Custom Flows](./examples/custom-flows.ts)** — Structured conversations with parameter collection
86
+
87
+ ## Configuration
88
+
89
+ ```typescript
90
+ interface TalkerConfig {
91
+ // Remote chatbot API (standalone mode — not needed in plugin mode)
92
+ chatbot?: {
93
+ url: string; // e.g., "https://bot.example.com/api/public/chat"
94
+ apiKey?: string; // Sent as x-api-key header
95
+ systemMessage?: string; // Override default system prompt
96
+ };
97
+
98
+ // Twilio credentials (optional — only needed for outbound SMS)
99
+ twilio?: {
100
+ accountSid?: string;
101
+ authToken?: string;
102
+ phoneNumber?: string;
103
+ };
104
+
105
+ // Phone number for human handoff
106
+ transferNumber?: string;
107
+
108
+ // Voice config per language (defaults: Polly voices for 6 languages)
109
+ voices?: Record<string, { voice: string; language: string }>;
110
+
111
+ // Structured flow definitions directory
112
+ flowsDir?: string;
113
+
114
+ // Custom language phrase files directory
115
+ languageDir?: string;
116
+
117
+ // Processing pipeline (pre/post-processing with OpenAI)
118
+ processing?: {
119
+ model?: string; // Default: "gpt-4o-mini"
120
+ incomingPromptPath?: string; // Custom incoming message prompt
121
+ outgoingPromptPath?: string; // Custom outgoing response prompt
122
+ };
123
+
124
+ // Feature flags
125
+ features?: {
126
+ thinkingAcknowledgmentEnabled?: boolean; // "One moment please" pattern
127
+ };
128
+
129
+ // Override OpenAI key (falls back to chatter's key in plugin mode)
130
+ openaiApiKey?: string;
131
+
132
+ // Route prefix for all endpoints. Default: ""
133
+ routePrefix?: string;
134
+
135
+ // Conversation TTL. Default: 30 minutes
136
+ contextTtlMs?: number;
137
+
138
+ // Max silence retries before ending call. Default: 3
139
+ maxNoSpeechRetries?: number;
140
+
141
+ // Custom chat function (overrides chatbot config and chatter RAG)
142
+ chatFn?: (phoneNumber: string, message: string) => Promise<string>;
143
+ }
144
+ ```
145
+
146
+ ## Twilio Setup
147
+
148
+ 1. Get a Twilio phone number
149
+ 2. Set webhook URLs in the Twilio console:
150
+
151
+ | Webhook | URL | Method |
152
+ |---|---|---|
153
+ | Voice | `https://your-server.com/call` | HTTP POST |
154
+ | SMS | `https://your-server.com/sms` | HTTP POST |
155
+ | Status Callback | `https://your-server.com/call/status` | HTTP POST |
156
+
157
+ ## Customization
158
+
159
+ ### Custom Flows
160
+
161
+ Flows are structured conversations with automatic parameter collection. Each flow is a directory with three files:
162
+
163
+ ```
164
+ config/flows/addNumbers/
165
+ flow.json — Definition (id, keywords, parameter schema)
166
+ handler.ts — Exports an execute() function
167
+ instructions.md — System prompt for parameter extraction
168
+ ```
169
+
170
+ **flow.json:**
171
+ ```json
172
+ {
173
+ "id": "addNumbers",
174
+ "name": "Add Two Numbers",
175
+ "description": "Adds two numbers together",
176
+ "triggerKeywords": ["add", "sum", "plus"],
177
+ "schema": {
178
+ "type": "object",
179
+ "properties": {
180
+ "firstNumber": { "type": "number", "description": "First number" },
181
+ "secondNumber": { "type": "number", "description": "Second number" }
182
+ },
183
+ "required": ["firstNumber", "secondNumber"]
184
+ }
185
+ }
186
+ ```
187
+
188
+ **handler.ts:**
189
+ ```typescript
190
+ import type { FlowHandlerResult, FlowHandlerContext } from '@diegoaltoworks/talker';
191
+
192
+ export async function execute(
193
+ params: Record<string, unknown>,
194
+ context: FlowHandlerContext,
195
+ ): Promise<FlowHandlerResult> {
196
+ const sum = Number(params.firstNumber) + Number(params.secondNumber);
197
+ return {
198
+ success: true,
199
+ result: sum,
200
+ say: `${params.firstNumber} plus ${params.secondNumber} equals ${sum}. Need anything else?`,
201
+ sms: `${params.firstNumber} + ${params.secondNumber} = ${sum}`,
202
+ };
203
+ }
204
+ ```
205
+
206
+ See [examples/custom-flows.ts](./examples/custom-flows.ts) for a complete walkthrough.
207
+
208
+ ### Custom Language Files
209
+
210
+ Override built-in phrases by providing a `languageDir`. Place JSON files named by language code (`en.json`, `fr.json`, etc.):
211
+
212
+ ```typescript
213
+ createTelephonyRoutes(app, deps, {
214
+ languageDir: './config/language',
215
+ });
216
+ ```
217
+
218
+ See [language/en.json](./language/en.json) for the expected structure.
219
+
220
+ ### Custom Prompts
221
+
222
+ Override the pre/post-processing system prompts:
223
+
224
+ ```typescript
225
+ createTelephonyRoutes(app, deps, {
226
+ processing: {
227
+ incomingPromptPath: './config/prompts/telephony-incoming.md',
228
+ outgoingPromptPath: './config/prompts/telephony-outgoing.md',
229
+ },
230
+ });
231
+ ```
232
+
233
+ See [prompts/incoming.md](./prompts/incoming.md) and [prompts/outgoing.md](./prompts/outgoing.md) for the default prompts.
234
+
235
+ ### Custom Voices
236
+
237
+ Override the default Polly TTS voices per language:
238
+
239
+ ```typescript
240
+ createTelephonyRoutes(app, deps, {
241
+ voices: {
242
+ en: { voice: 'Polly.Amy', language: 'en-US' },
243
+ fr: { voice: 'Polly.Lea', language: 'fr-FR' },
244
+ },
245
+ });
246
+ ```
247
+
248
+ ## Architecture
249
+
250
+ ```
251
+ Phone Call / SMS
252
+ |
253
+ v
254
+ Twilio (ASR / TTS / SMS gateway)
255
+ |
256
+ v POST /call or /sms
257
+ Talker (Hono routes)
258
+ |-- processIncoming (OpenAI: language detect, transfer intent, STT cleanup)
259
+ |-- Flow Engine (LLM intent detect + parameter extraction)
260
+ |-- chatFn / Chatter RAG pipeline
261
+ |-- processOutgoing (OpenAI: channel formatting, translation)
262
+ |
263
+ v TwiML response
264
+ Twilio (speaks / sends to caller)
265
+ ```
266
+
267
+ **Call lifecycle:** Twilio posts to `/call` on ring, `/call/respond` on speech, `/call/no-speech` on silence, `/call/answer` after async acknowledgment, and `/call/status` on hangup.
268
+
269
+ ## Project Structure
270
+
271
+ | Directory | What lives there |
272
+ |---|---|
273
+ | `src/core/processing/` | OpenAI-powered incoming pre-processor and outgoing post-processor |
274
+ | `src/core/chatbot/` | HTTP client for remote chatbot APIs (standalone mode) |
275
+ | `src/core/` | Context store, TwiML generation, voice config, phrases, logger |
276
+ | `src/flows/` | Flow engine — registry, intent detection, parameter extraction, lifecycle |
277
+ | `src/routes/call/` | Individual Hono handlers for each Twilio voice webhook |
278
+ | `src/routes/sms/` | Hono handlers for SMS webhooks |
279
+ | `src/adapters/` | Twilio REST API client (outbound SMS) |
280
+ | `examples/` | Ready-to-run examples for plugin, standalone, and custom flows |
281
+ | `language/` | Built-in phrase files (en, fr, de, nl, es, pt) |
282
+ | `prompts/` | Default system prompts for the processing pipeline |
283
+
284
+ ## Development
285
+
286
+ ```bash
287
+ bun install
288
+ bun test # Run all tests (66 tests)
289
+ bun run test:unit # Unit tests only
290
+ bun run test:integration # Integration tests (some require OPENAI_API_KEY)
291
+ bun run typecheck # Type checking
292
+ bun run lint # Biome linting
293
+ bun run check # All checks (typecheck + lint + test)
294
+ bun run build # Build for npm (dual ESM/CJS)
295
+ ```
296
+
297
+ ## License
298
+
299
+ MIT
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Twilio Adapter
3
+ *
4
+ * Handles outbound SMS sending via Twilio's REST API.
5
+ * TwiML generation is handled by src/core/twiml.ts.
6
+ */
7
+ import type { TwilioConfig } from "../types";
8
+ /**
9
+ * Send an SMS via Twilio REST API
10
+ */
11
+ export declare function sendSMS(config: TwilioConfig, to: string, message: string): Promise<boolean>;
12
+ //# sourceMappingURL=twilio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twilio.d.ts","sourceRoot":"","sources":["../../src/adapters/twilio.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C;;GAEG;AACH,wBAAsB,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAyCjG"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Chat Function
3
+ *
4
+ * Resolves a chat response using the first available method:
5
+ * 1. chatFn (custom function override)
6
+ * 2. chatbot config (remote HTTP API — standalone mode)
7
+ * 3. chatter RAG pipeline (plugin mode)
8
+ */
9
+ import type { TalkerDependencies } from "../types";
10
+ /**
11
+ * Get a chat response
12
+ */
13
+ export declare function chat(deps: TalkerDependencies, phoneNumber: string, message: string): Promise<string>;
14
+ //# sourceMappingURL=chat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/core/chat.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAKnD;;GAEG;AACH,wBAAsB,IAAI,CACxB,IAAI,EAAE,kBAAkB,EACxB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAmCjB"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * HTTP Chatbot Client
3
+ *
4
+ * Calls a remote chatbot API (e.g., chatter's /api/public/chat) over HTTP.
5
+ * Maintains multi-turn conversation history per phone number.
6
+ */
7
+ import type { ChatbotConfig } from "../../types";
8
+ /**
9
+ * Send a message to the remote chatbot API and get a response
10
+ */
11
+ export declare function chatViaHTTP(config: ChatbotConfig, phoneNumber: string, message: string): Promise<string>;
12
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/core/chatbot/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AASjD;;GAEG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CA8DjB"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Chatbot Conversation Store
3
+ *
4
+ * Tracks multi-turn conversation history per phone number for the HTTP chatbot client.
5
+ * Only used in standalone mode (plugin mode uses chatter's own conversation handling).
6
+ */
7
+ import type { ChatConversation } from "./types";
8
+ export declare function getOrCreateConversation(phoneNumber: string, systemMessage?: string): ChatConversation;
9
+ export declare function addUserMessage(phoneNumber: string, content: string, systemMessage?: string): void;
10
+ export declare function addBotMessage(phoneNumber: string, content: string, systemMessage?: string): void;
11
+ export declare function getConversation(phoneNumber: string): ChatConversation | undefined;
12
+ export declare function clearConversation(phoneNumber: string): void;
13
+ export declare function clearAllConversations(): void;
14
+ //# sourceMappingURL=conversations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversations.d.ts","sourceRoot":"","sources":["../../../src/core/chatbot/conversations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAe,MAAM,SAAS,CAAC;AAI7D,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,aAAa,CAAC,EAAE,MAAM,GACrB,gBAAgB,CAoBlB;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAIjG;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAIhG;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAEjF;AAED,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Chatbot Client
3
+ *
4
+ * Re-exports for the HTTP chatbot client module.
5
+ */
6
+ export { chatViaHTTP } from "./client";
7
+ export { clearAllConversations, clearConversation, getConversation, getOrCreateConversation, } from "./conversations";
8
+ export type { ChatConversation, ChatMessage, ChatbotRequest, ChatbotResponse } from "./types";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/chatbot/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,EACf,uBAAuB,GACxB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Chatbot Client Types
3
+ *
4
+ * Matches chatter's /api/public/chat request/response format.
5
+ */
6
+ export interface ChatMessage {
7
+ role: "user" | "assistant" | "system";
8
+ content: string;
9
+ }
10
+ export interface ChatbotRequest {
11
+ /** Single message (simple mode) */
12
+ message?: string;
13
+ /** Full conversation history (multi-turn mode) */
14
+ messages?: ChatMessage[];
15
+ }
16
+ export interface ChatbotResponse {
17
+ reply: string;
18
+ }
19
+ export interface ChatConversation {
20
+ conversationId: string;
21
+ chatHistory: ChatMessage[];
22
+ createdAt: number;
23
+ lastActivityAt: number;
24
+ }
25
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/chatbot/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,WAAW,EAAE,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Conversation Context Store
3
+ *
4
+ * In-memory Map-based context management for telephony sessions.
5
+ * Stores per-phone-number state: language, message history, active flow, retry counts.
6
+ */
7
+ import type { Channel, FlowState, TelephonyContext } from "../types";
8
+ /**
9
+ * Start periodic cleanup of stale contexts
10
+ */
11
+ export declare function startCleanup(ttlMs: number, intervalMs: number): void;
12
+ /**
13
+ * Stop periodic cleanup (for testing / shutdown)
14
+ */
15
+ export declare function stopCleanup(): void;
16
+ /**
17
+ * Get or create a context for a phone number
18
+ */
19
+ export declare function getOrCreateContext(phoneNumber: string, channel?: Channel): TelephonyContext;
20
+ /**
21
+ * Get context without creating one
22
+ */
23
+ export declare function getContext(phoneNumber: string): TelephonyContext | undefined;
24
+ /**
25
+ * Set detected language (first detection wins)
26
+ */
27
+ export declare function setDetectedLanguage(phoneNumber: string, language: string): void;
28
+ /**
29
+ * Get detected language for a phone number
30
+ */
31
+ export declare function getDetectedLanguage(phoneNumber: string): string | null;
32
+ /**
33
+ * Add a message to conversation history
34
+ */
35
+ export declare function addMessage(phoneNumber: string, role: "user" | "assistant", content: string, channel?: Channel): void;
36
+ /**
37
+ * Get message history for a phone number
38
+ */
39
+ export declare function getMessageHistory(phoneNumber: string): Array<{
40
+ role: "user" | "assistant";
41
+ content: string;
42
+ timestamp: number;
43
+ }>;
44
+ /**
45
+ * Clear all context for a phone number
46
+ */
47
+ export declare function clearContext(phoneNumber: string): void;
48
+ export declare function setActiveFlow(phoneNumber: string, flowName: string, params?: Record<string, unknown>): void;
49
+ export declare function getActiveFlow(phoneNumber: string): FlowState | null;
50
+ export declare function updateFlowParams(phoneNumber: string, params: Record<string, unknown>): void;
51
+ export declare function clearActiveFlow(phoneNumber: string): void;
52
+ export declare function incrementNoSpeechRetries(phoneNumber: string): number;
53
+ export declare function getNoSpeechRetries(phoneNumber: string): number;
54
+ export declare function resetNoSpeechRetries(phoneNumber: string): void;
55
+ export declare function setLastPrompt(phoneNumber: string, prompt: string): void;
56
+ export declare function getLastPrompt(phoneNumber: string): string | null;
57
+ /**
58
+ * Clear all contexts (for testing)
59
+ */
60
+ export declare function clearAllContexts(): void;
61
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/core/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAOrE;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAWpE;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAKlC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,OAAgB,GACxB,gBAAgB,CAqBlB;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAE5E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAM/E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEtE;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GAAG,WAAW,EAC1B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,OAAgB,GACxB,IAAI,CAON;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,GAClB,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAE3E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAGtD;AAID,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACnC,IAAI,CAWN;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEnE;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAM3F;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAMzD;AAID,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAMpE;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAK9D;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAGvE;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEhE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=context.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.test.d.ts","sourceRoot":"","sources":["../../src/core/context.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Error handling utilities
3
+ */
4
+ /**
5
+ * Extract error message from unknown error type
6
+ */
7
+ export declare function getErrorMessage(error: unknown): string;
8
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQtD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=errors.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.test.d.ts","sourceRoot":"","sources":["../../src/core/errors.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Structured JSON logger
3
+ *
4
+ * Silent during tests unless DEBUG=true.
5
+ */
6
+ export declare const logger: {
7
+ info: (message: string, data?: Record<string, unknown>) => void;
8
+ warn: (message: string, data?: Record<string, unknown>) => void;
9
+ error: (message: string, data?: Record<string, unknown>) => void;
10
+ };
11
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAuBH,eAAO,MAAM,MAAM;oBACD,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;oBACtC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;qBACrC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CACxD,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Multi-language phrase system
3
+ *
4
+ * Loads phrase files from a configurable directory.
5
+ * Falls back to built-in English phrases if language files are not found.
6
+ */
7
+ import type { Phrases } from "../types";
8
+ /**
9
+ * Load phrases for a language from a directory
10
+ */
11
+ export declare function loadPhrases(language: string, languageDir?: string): Phrases;
12
+ type SimplePhraseKey = "greeting" | "didNotCatch" | "didNotHear" | "didNotHearRetry" | "didNotHearFinal" | "transfer" | "acknowledgment" | "error" | "timeout" | "lostQuestion";
13
+ /**
14
+ * Get a simple phrase by key
15
+ */
16
+ export declare function getPhrase(language: string, key: SimplePhraseKey, languageDir?: string): string;
17
+ /**
18
+ * Get a time-of-day farewell phrase
19
+ */
20
+ export declare function getFarewellPhrase(language: string, languageDir?: string): string;
21
+ /**
22
+ * Get a flow-related phrase
23
+ */
24
+ export declare function getFlowPhrase(language: string, key: keyof Phrases["flow"], languageDir?: string): string;
25
+ /**
26
+ * Get an SMS-specific phrase
27
+ */
28
+ export declare function getSmsPhrase(language: string, key: keyof Phrases["sms"], languageDir?: string): string;
29
+ export {};
30
+ //# sourceMappingURL=phrases.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phrases.d.ts","sourceRoot":"","sources":["../../src/core/phrases.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAIxC;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CA4B3E;AAED,KAAK,eAAe,GAChB,UAAU,GACV,aAAa,GACb,YAAY,GACZ,iBAAiB,GACjB,iBAAiB,GACjB,UAAU,GACV,gBAAgB,GAChB,OAAO,GACP,SAAS,GACT,cAAc,CAAC;AAEnB;;GAEG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAG9F;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAWhF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,EAC1B,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,CAGR;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,EACzB,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,CAGR"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=phrases.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phrases.test.d.ts","sourceRoot":"","sources":["../../src/core/phrases.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Incoming Message Processor
3
+ *
4
+ * Pre-processes incoming messages: language detection, transfer intent,
5
+ * end-call detection, and STT artifact cleanup.
6
+ */
7
+ import type { Channel, IncomingResult, TalkerDependencies } from "../../types";
8
+ /**
9
+ * Pre-process an incoming message
10
+ */
11
+ export declare function processIncoming(deps: TalkerDependencies, phoneNumber: string, userMessage: string, channel?: Channel): Promise<IncomingResult>;
12
+ //# sourceMappingURL=incoming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"incoming.d.ts","sourceRoot":"","sources":["../../../src/core/processing/incoming.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAa/E;;GAEG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,kBAAkB,EACxB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,OAAgB,GACxB,OAAO,CAAC,cAAc,CAAC,CAqEzB"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Processing Pipeline
3
+ *
4
+ * Re-exports the incoming and outgoing processors.
5
+ */
6
+ export { processIncoming } from "./incoming";
7
+ export { processOutgoing } from "./outgoing";
8
+ export { callOpenAI } from "./openai";
9
+ export { resetPromptCache } from "./prompts";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/processing/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * OpenAI API Client
3
+ *
4
+ * Low-level fetch wrapper for the talker processing pipeline.
5
+ * Uses fetch directly (no SDK) to keep dependencies minimal.
6
+ */
7
+ import type { TalkerDependencies } from "../../types";
8
+ /**
9
+ * Call OpenAI chat completions API
10
+ */
11
+ export declare function callOpenAI(deps: TalkerDependencies, systemPrompt: string, userMessage: string, context: {
12
+ phoneNumber: string;
13
+ stage: "incoming" | "outgoing";
14
+ }): Promise<string>;
15
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/core/processing/openai.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAKtD;;GAEG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,kBAAkB,EACxB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAAA;CAAE,GAC/D,OAAO,CAAC,MAAM,CAAC,CAoDjB"}