lua-cli 3.17.6 → 3.18.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.
@@ -9,403 +9,6 @@ var __export = (target, all) => {
9
9
  __defProp(target, name, { get: all[name], enumerable: true });
10
10
  };
11
11
 
12
- // src/interfaces/baskets.ts
13
- var BasketStatus;
14
- var init_baskets = __esm({
15
- "src/interfaces/baskets.ts"() {
16
- "use strict";
17
- BasketStatus = /* @__PURE__ */ (function(BasketStatus2) {
18
- BasketStatus2["ACTIVE"] = "active";
19
- BasketStatus2["CHECKED_OUT"] = "checked_out";
20
- BasketStatus2["ABANDONED"] = "abandoned";
21
- BasketStatus2["EXPIRED"] = "expired";
22
- return BasketStatus2;
23
- })({});
24
- }
25
- });
26
-
27
- // src/config/constants.ts
28
- import { join } from "path";
29
- import { homedir } from "os";
30
- var CLI_CONFIG_DIR, VERSION_CHECK_FILE, TELEMETRY_FILE, CLI_CACHE_FILE, BASE_URLS, CREDENTIALS_FILE, SANDBOX_STORAGE_FILE, AUTH_STORAGE_FILE;
31
- var init_constants = __esm({
32
- "src/config/constants.ts"() {
33
- "use strict";
34
- CLI_CONFIG_DIR = join(homedir(), ".lua-cli");
35
- VERSION_CHECK_FILE = join(CLI_CONFIG_DIR, "version-check.json");
36
- TELEMETRY_FILE = join(CLI_CONFIG_DIR, "telemetry.json");
37
- CLI_CACHE_FILE = join(CLI_CONFIG_DIR, "cache.json");
38
- BASE_URLS = {
39
- API: process.env.LUA_API_URL || "https://api.heylua.ai",
40
- AUTH: process.env.LUA_AUTH_URL || "https://auth.heylua.ai",
41
- CHAT: process.env.LUA_API_URL || "https://api.heylua.ai",
42
- WEBHOOK: "https://webhook.heylua.ai",
43
- CDN: "https://cdn.heylua.ai"
44
- };
45
- CREDENTIALS_FILE = join(CLI_CONFIG_DIR, "credentials");
46
- SANDBOX_STORAGE_FILE = join(CLI_CONFIG_DIR, "sandbox.json");
47
- AUTH_STORAGE_FILE = join(CLI_CONFIG_DIR, "auth.json");
48
- }
49
- });
50
-
51
- // src/errors/auth.error.ts
52
- var AuthenticationError;
53
- var init_auth_error = __esm({
54
- "src/errors/auth.error.ts"() {
55
- "use strict";
56
- AuthenticationError = class _AuthenticationError extends Error {
57
- static {
58
- __name(this, "AuthenticationError");
59
- }
60
- statusCode = 401;
61
- isAuthenticationError = true;
62
- reason;
63
- serverMessage;
64
- /**
65
- * If true, the error message already contains complete remediation steps
66
- * and `withErrorHandling` should not append its own hint block. Use this
67
- * when the throw site has more context about the right fix than the
68
- * generic per-reason hints (e.g. `getToken()` listing all three ways to
69
- * configure a key — keychain, env var, .env file).
70
- */
71
- suppressDefaultRemediation;
72
- constructor(message = "Invalid API key", reason = "unknown", serverMessage, suppressDefaultRemediation = false) {
73
- super(message);
74
- this.name = "AuthenticationError";
75
- this.reason = reason;
76
- this.serverMessage = serverMessage;
77
- this.suppressDefaultRemediation = suppressDefaultRemediation;
78
- if (Error.captureStackTrace) {
79
- Error.captureStackTrace(this, _AuthenticationError);
80
- }
81
- }
82
- /**
83
- * Checks if an error is an AuthenticationError
84
- * @param error - The error to check
85
- * @returns True if the error is an AuthenticationError
86
- */
87
- static isAuthenticationError(error) {
88
- return error instanceof _AuthenticationError || error instanceof Error && "isAuthenticationError" in error && error.isAuthenticationError === true;
89
- }
90
- };
91
- }
92
- });
93
-
94
- // src/api/http.client.ts
95
- import { randomUUID } from "crypto";
96
- var HttpClient;
97
- var init_http_client = __esm({
98
- "src/api/http.client.ts"() {
99
- "use strict";
100
- init_auth_error();
101
- HttpClient = class {
102
- static {
103
- __name(this, "HttpClient");
104
- }
105
- baseUrl;
106
- /**
107
- * Creates an instance of HttpClient
108
- * @param baseUrl - The base URL for all API requests
109
- */
110
- constructor(baseUrl) {
111
- this.baseUrl = baseUrl;
112
- }
113
- /**
114
- * Makes an HTTP request with standardized error handling
115
- * @param url - The full URL to request
116
- * @param options - Fetch API request options
117
- * @returns Promise resolving to an ApiResponse with typed data
118
- * @private
119
- */
120
- async request(url, options = {}) {
121
- const controller = new AbortController();
122
- const timeoutId = setTimeout(() => controller.abort(), 3e4);
123
- try {
124
- const response = await fetch(url, {
125
- ...options,
126
- signal: controller.signal,
127
- headers: {
128
- "Content-Type": "application/json",
129
- ...options.headers
130
- }
131
- });
132
- clearTimeout(timeoutId);
133
- if (!response.ok) {
134
- let errorData;
135
- try {
136
- errorData = await response.json();
137
- } catch (jsonError) {
138
- errorData = {};
139
- }
140
- if (response.status === 401) {
141
- const serverMessage = typeof errorData.message === "string" ? errorData.message : void 0;
142
- if (serverMessage && /not an admin/i.test(serverMessage)) {
143
- throw new AuthenticationError(`Access denied for this agent: ${serverMessage}`, "no_agent_access", serverMessage);
144
- }
145
- const isExplicitCredential = !!serverMessage && /(invalid|expired|missing|no)\s+(api[\s_-]?key|token|credential)/i.test(serverMessage);
146
- const isBareAuthRejection = !serverMessage || /^unauthorized$/i.test(serverMessage);
147
- if (isExplicitCredential || isBareAuthRejection) {
148
- throw new AuthenticationError("Authentication failed. Your API key may be invalid or expired.", "invalid_credentials", serverMessage);
149
- }
150
- throw new AuthenticationError(`Authentication failed: ${serverMessage}`, "unknown", serverMessage);
151
- }
152
- if (response.status === 403) {
153
- const detail = errorData.message || "You do not have permission to access this resource.";
154
- throw new Error(`Access denied (403): ${detail}
155
- Check that your API key has access to this agent/organization.`);
156
- }
157
- return {
158
- success: false,
159
- error: {
160
- message: errorData.message || `HTTP ${response.status}: ${response.statusText}`,
161
- statusCode: response.status,
162
- error: errorData.error,
163
- ...errorData
164
- }
165
- };
166
- }
167
- let data;
168
- try {
169
- data = await response.json();
170
- } catch (jsonError) {
171
- data = {};
172
- }
173
- if (typeof data === "object" && data !== null && "success" in data) {
174
- return data;
175
- }
176
- return {
177
- success: true,
178
- data
179
- };
180
- } catch (error) {
181
- clearTimeout(timeoutId);
182
- if (AuthenticationError.isAuthenticationError(error)) {
183
- throw error;
184
- }
185
- if (error instanceof Error && error.message.startsWith("Access denied (403)")) {
186
- throw error;
187
- }
188
- if (error instanceof DOMException && error.name === "AbortError") {
189
- return {
190
- success: false,
191
- error: {
192
- message: "Request timeout (30s)",
193
- statusCode: 0
194
- }
195
- };
196
- }
197
- return {
198
- success: false,
199
- error: {
200
- message: error instanceof Error ? error.message : "Network request failed",
201
- statusCode: 0
202
- }
203
- };
204
- }
205
- }
206
- /**
207
- * Checks if an HTTP status code is retryable
208
- * @param statusCode - The HTTP status code (0 for network errors)
209
- * @returns True if the request should be retried
210
- * @private
211
- */
212
- isRetryableStatus(statusCode) {
213
- return statusCode === 0 || statusCode === 429 || statusCode >= 500 && statusCode <= 504;
214
- }
215
- /**
216
- * Calculates exponential backoff with full jitter (AWS best practice)
217
- * @param attempt - The retry attempt number (0-based)
218
- * @param baseMs - Base delay in milliseconds
219
- * @param maxMs - Maximum delay cap in milliseconds
220
- * @returns Delay in milliseconds with random jitter
221
- * @private
222
- */
223
- calculateBackoff(attempt, baseMs = 1e3, maxMs = 15e3) {
224
- const exponential = Math.min(maxMs, baseMs * Math.pow(2, attempt));
225
- return Math.max(100, Math.random() * exponential);
226
- }
227
- /**
228
- * Wraps request with retry logic for transient failures
229
- * @param url - The full URL to request
230
- * @param options - Fetch API request options
231
- * @param maxRetries - Maximum number of retry attempts (default 3)
232
- * @returns Promise resolving to an ApiResponse with typed data
233
- * @private
234
- */
235
- async retryableRequest(url, options = {}, maxRetries = 3) {
236
- if (options.method === "POST") {
237
- const headers = options.headers || {};
238
- if (!headers["X-Idempotency-Key"]) {
239
- headers["X-Idempotency-Key"] = randomUUID();
240
- options = {
241
- ...options,
242
- headers: {
243
- ...options.headers,
244
- ...headers
245
- }
246
- };
247
- }
248
- }
249
- let lastResult = null;
250
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
251
- try {
252
- const result = await this.request(url, options);
253
- if (result.success || !result.error || !this.isRetryableStatus(result.error.statusCode || 0)) {
254
- return result;
255
- }
256
- lastResult = result;
257
- } catch (error) {
258
- throw error;
259
- }
260
- if (attempt < maxRetries) {
261
- const backoff = this.calculateBackoff(attempt);
262
- await new Promise((resolve) => setTimeout(resolve, backoff));
263
- }
264
- }
265
- return lastResult;
266
- }
267
- /**
268
- * Performs an HTTP GET request
269
- * @param url - The relative URL path to request (will be appended to baseUrl)
270
- * @param headers - Optional HTTP headers to include in the request
271
- * @returns Promise resolving to an ApiResponse with typed data
272
- * @protected
273
- */
274
- async httpGet(url, headers) {
275
- return this.retryableRequest(this.baseUrl + url, {
276
- method: "GET",
277
- headers
278
- });
279
- }
280
- /**
281
- * Performs an HTTP POST request
282
- * @param url - The relative URL path to request (will be appended to baseUrl)
283
- * @param data - Optional request body data (will be JSON stringified)
284
- * @param headers - Optional HTTP headers to include in the request
285
- * @returns Promise resolving to an ApiResponse with typed data
286
- * @protected
287
- */
288
- async httpPost(url, data, headers) {
289
- return this.retryableRequest(this.baseUrl + url, {
290
- method: "POST",
291
- body: data ? JSON.stringify(data) : void 0,
292
- headers
293
- });
294
- }
295
- /**
296
- * Performs an HTTP PUT request
297
- * @param url - The relative URL path to request (will be appended to baseUrl)
298
- * @param data - Optional request body data (will be JSON stringified)
299
- * @param headers - Optional HTTP headers to include in the request
300
- * @returns Promise resolving to an ApiResponse with typed data
301
- * @protected
302
- */
303
- async httpPut(url, data, headers) {
304
- return this.retryableRequest(this.baseUrl + url, {
305
- method: "PUT",
306
- body: data ? JSON.stringify(data) : void 0,
307
- headers
308
- });
309
- }
310
- /**
311
- * Performs an HTTP DELETE request
312
- * @param url - The relative URL path to request (will be appended to baseUrl)
313
- * @param headers - Optional HTTP headers to include in the request
314
- * @returns Promise resolving to an ApiResponse with typed data
315
- * @protected
316
- */
317
- async httpDelete(url, headers) {
318
- return this.retryableRequest(this.baseUrl + url, {
319
- method: "DELETE",
320
- headers
321
- });
322
- }
323
- /**
324
- * Performs an HTTP PATCH request
325
- * @param url - The relative URL path to request (will be appended to baseUrl)
326
- * @param data - Optional request body data (will be JSON stringified)
327
- * @param headers - Optional HTTP headers to include in the request
328
- * @returns Promise resolving to an ApiResponse with typed data
329
- * @protected
330
- */
331
- async httpPatch(url, data, headers) {
332
- return this.retryableRequest(this.baseUrl + url, {
333
- method: "PATCH",
334
- body: data ? JSON.stringify(data) : void 0,
335
- headers
336
- });
337
- }
338
- };
339
- }
340
- });
341
-
342
- // src/api/auth.api.service.ts
343
- var init_auth_api_service = __esm({
344
- "src/api/auth.api.service.ts"() {
345
- "use strict";
346
- init_http_client();
347
- }
348
- });
349
-
350
- // src/services/auth.ts
351
- import "dotenv/config";
352
- import { readFileSync, writeFileSync, mkdirSync, unlinkSync } from "fs";
353
- function getToken() {
354
- if (process.env.LUA_API_KEY) {
355
- return process.env.LUA_API_KEY;
356
- }
357
- try {
358
- const token = readFileSync(CREDENTIALS_FILE, "utf8").trim();
359
- if (token) return token;
360
- } catch {
361
- }
362
- throw new AuthenticationError('No API key found.\n\n Authenticate using one of these methods:\n\n \u279C lua auth configure\n \u279C export LUA_API_KEY="your-api-key-here"\n \u279C Add LUA_API_KEY=... to a .env file\n\n \u{1F511} Get your API key at https://admin.heylua.ai', "invalid_credentials", void 0, true);
363
- }
364
- var init_auth = __esm({
365
- "src/services/auth.ts"() {
366
- "use strict";
367
- init_auth_api_service();
368
- init_constants();
369
- init_auth_error();
370
- __name(getToken, "getToken");
371
- }
372
- });
373
-
374
- // src/config/compile.constants.ts
375
- var COMPILE_DIRS, COMPILE_FILES, SKILL_DEFAULTS, YAML_FORMAT;
376
- var init_compile_constants = __esm({
377
- "src/config/compile.constants.ts"() {
378
- "use strict";
379
- COMPILE_DIRS = {
380
- DIST: "dist",
381
- DIST_V2: "dist-v2",
382
- LUA: ".lua",
383
- TOOLS: "tools"
384
- };
385
- COMPILE_FILES = {
386
- DEPLOYMENT_JSON: "deployment.json",
387
- DEPLOY_JSON: "deploy.json",
388
- MANIFEST_JSON: "manifest.json",
389
- INDEX_TS: "index.ts",
390
- INDEX_JS: "index.js",
391
- PACKAGE_JSON: "package.json",
392
- TSCONFIG_JSON: "tsconfig.json",
393
- LUA_SKILL_YAML: "lua.skill.yaml"
394
- };
395
- SKILL_DEFAULTS = {
396
- NAME: "lua-skill",
397
- VERSION: "1.0.0",
398
- DESCRIPTION: "",
399
- CONTEXT: ""
400
- };
401
- YAML_FORMAT = {
402
- INDENT: 2,
403
- LINE_WIDTH: -1,
404
- NO_REFS: true
405
- };
406
- }
407
- });
408
-
409
12
  // ../shared-types/dist/index.mjs
410
13
  import { z } from "zod";
411
14
  function isPersonaTextObject(value) {
@@ -470,6 +73,14 @@ function aiGenerateInputFromSimplified(prompt, content) {
470
73
  ]
471
74
  };
472
75
  }
76
+ function isInteractiveChannel(channel) {
77
+ if (!channel) return true;
78
+ return !NON_INTERACTIVE_CHANNELS.includes(channel);
79
+ }
80
+ function isInteractiveTurn(turn) {
81
+ if (typeof turn.interactive === "boolean") return turn.interactive;
82
+ return isInteractiveChannel(turn.channel);
83
+ }
473
84
  function removeNavigateBlock(input) {
474
85
  return input.replace(/::: navigate[\s\S]*?:::/g, "").trim();
475
86
  }
@@ -537,7 +148,7 @@ function transformChatHistoryContentParts(parts) {
537
148
  function buildDefaultPersona(agentName) {
538
149
  return DEFAULT_PERSONA_GUIDE.replace(AGENT_NAME_TOKEN, () => agentName || "My Agent");
539
150
  }
540
- var __defProp2, __name2, AGENT_NAME_TOKEN, DEFAULT_PERSONA_GUIDE, VoiceNameSchema, PluginProviderSchema, RealtimeProviderSchema, PluginClassSchema, ModelDescriptorSchema, InferenceModelSchema, PluginModelSchema, RealtimeModelSchema, LuaVoiceModelSchema, TurnDetectionSchema, InterruptionSchema, BuiltinAudioClipSchema, AudioConfigSchema, BackgroundAudioEntrySchema, BackgroundAudioSchema, LuaVoiceConfigInnerSchema, LuaVoiceConfigSchema, LuaVoiceRefSchema;
151
+ var __defProp2, __name2, CHANNEL_SEND_CHANNELS, NON_INTERACTIVE_CHANNELS, AGENT_NAME_TOKEN, DEFAULT_PERSONA_GUIDE, VoiceNameSchema, PluginProviderSchema, RealtimeProviderSchema, PluginClassSchema, ModelDescriptorSchema, InferenceModelSchema, PluginModelSchema, RealtimeModelSchema, LuaVoiceModelSchema, TurnDetectionSchema, InterruptionSchema, BuiltinAudioClipSchema, AudioConfigSchema, BackgroundAudioEntrySchema, BackgroundAudioSchema, LuaVoiceConfigInnerSchema, LuaVoiceConfigSchema, LuaVoiceRefSchema;
541
152
  var init_dist = __esm({
542
153
  "../shared-types/dist/index.mjs"() {
543
154
  "use strict";
@@ -555,6 +166,23 @@ var init_dist = __esm({
555
166
  __name2(personaToLiteral, "personaToLiteral");
556
167
  __name(aiGenerateInputFromSimplified, "aiGenerateInputFromSimplified");
557
168
  __name2(aiGenerateInputFromSimplified, "aiGenerateInputFromSimplified");
169
+ CHANNEL_SEND_CHANNELS = [
170
+ "whatsapp",
171
+ "sms",
172
+ "email",
173
+ "webchat",
174
+ "teams",
175
+ "instagram",
176
+ "messenger"
177
+ ];
178
+ NON_INTERACTIVE_CHANNELS = [
179
+ "trigger",
180
+ "agent-invocation"
181
+ ];
182
+ __name(isInteractiveChannel, "isInteractiveChannel");
183
+ __name2(isInteractiveChannel, "isInteractiveChannel");
184
+ __name(isInteractiveTurn, "isInteractiveTurn");
185
+ __name2(isInteractiveTurn, "isInteractiveTurn");
558
186
  __name(removeNavigateBlock, "removeNavigateBlock");
559
187
  __name2(removeNavigateBlock, "removeNavigateBlock");
560
188
  __name(transformChatHistoryContentParts, "transformChatHistoryContentParts");
@@ -796,7 +424,15 @@ Feel free to add, remove, or rename sections. Your persona can be a single parag
796
424
  // to the LLM as a ToolError — fills the 2–3s gap before the LLM's own
797
425
  // recovery response. Persona-specific (keep it short and on-brand);
798
426
  // absent → no spoken fallback (the LLM's recovery is the only signal).
799
- onToolFailureSay: z.string().min(1).max(200).optional()
427
+ onToolFailureSay: z.string().min(1).max(200).optional(),
428
+ // Tool names to withhold from this voice agent's session. Matches ANY
429
+ // resolved tool: the platform base tools (searchKnowledgeBase, searchWeb,
430
+ // geocoding, the send* structured-output family), MCP/device tools, and the
431
+ // agent's own skill tools compiled into the artifact. Typical use is dropping
432
+ // the on-screen send* tools (`sendPayment`, `sendListItems`, …) on a
433
+ // screenless phone agent where they have nowhere to render. Names that match
434
+ // nothing are ignored (warn, not error) so a typo can't fail the push.
435
+ excludeTools: z.array(z.string().min(1)).optional()
800
436
  });
801
437
  LuaVoiceConfigSchema = LuaVoiceConfigInnerSchema.superRefine((cfg, ctx) => {
802
438
  const isRealtime = cfg.llm.kind === "realtime";
@@ -839,11 +475,408 @@ Feel free to add, remove, or rename sections. Your persona can be a single parag
839
475
  });
840
476
  }
841
477
  }
842
- });
843
- LuaVoiceRefSchema = z.object({
844
- voiceId: z.string().min(1),
845
- version: z.string().optional()
846
- });
478
+ });
479
+ LuaVoiceRefSchema = z.object({
480
+ voiceId: z.string().min(1),
481
+ version: z.string().optional()
482
+ });
483
+ }
484
+ });
485
+
486
+ // src/interfaces/baskets.ts
487
+ var BasketStatus;
488
+ var init_baskets = __esm({
489
+ "src/interfaces/baskets.ts"() {
490
+ "use strict";
491
+ BasketStatus = /* @__PURE__ */ (function(BasketStatus2) {
492
+ BasketStatus2["ACTIVE"] = "active";
493
+ BasketStatus2["CHECKED_OUT"] = "checked_out";
494
+ BasketStatus2["ABANDONED"] = "abandoned";
495
+ BasketStatus2["EXPIRED"] = "expired";
496
+ return BasketStatus2;
497
+ })({});
498
+ }
499
+ });
500
+
501
+ // src/config/constants.ts
502
+ import { join } from "path";
503
+ import { homedir } from "os";
504
+ var CLI_CONFIG_DIR, VERSION_CHECK_FILE, TELEMETRY_FILE, CLI_CACHE_FILE, BASE_URLS, CREDENTIALS_FILE, SANDBOX_STORAGE_FILE, AUTH_STORAGE_FILE;
505
+ var init_constants = __esm({
506
+ "src/config/constants.ts"() {
507
+ "use strict";
508
+ CLI_CONFIG_DIR = join(homedir(), ".lua-cli");
509
+ VERSION_CHECK_FILE = join(CLI_CONFIG_DIR, "version-check.json");
510
+ TELEMETRY_FILE = join(CLI_CONFIG_DIR, "telemetry.json");
511
+ CLI_CACHE_FILE = join(CLI_CONFIG_DIR, "cache.json");
512
+ BASE_URLS = {
513
+ API: process.env.LUA_API_URL || "https://api.heylua.ai",
514
+ AUTH: process.env.LUA_AUTH_URL || "https://auth.heylua.ai",
515
+ CHAT: process.env.LUA_API_URL || "https://api.heylua.ai",
516
+ WEBHOOK: process.env.LUA_WEBHOOK_URL || "https://webhook.heylua.ai",
517
+ CDN: "https://cdn.heylua.ai"
518
+ };
519
+ CREDENTIALS_FILE = join(CLI_CONFIG_DIR, "credentials");
520
+ SANDBOX_STORAGE_FILE = join(CLI_CONFIG_DIR, "sandbox.json");
521
+ AUTH_STORAGE_FILE = join(CLI_CONFIG_DIR, "auth.json");
522
+ }
523
+ });
524
+
525
+ // src/errors/auth.error.ts
526
+ var AuthenticationError;
527
+ var init_auth_error = __esm({
528
+ "src/errors/auth.error.ts"() {
529
+ "use strict";
530
+ AuthenticationError = class _AuthenticationError extends Error {
531
+ static {
532
+ __name(this, "AuthenticationError");
533
+ }
534
+ statusCode = 401;
535
+ isAuthenticationError = true;
536
+ reason;
537
+ serverMessage;
538
+ /**
539
+ * If true, the error message already contains complete remediation steps
540
+ * and `withErrorHandling` should not append its own hint block. Use this
541
+ * when the throw site has more context about the right fix than the
542
+ * generic per-reason hints (e.g. `getToken()` listing all three ways to
543
+ * configure a key — keychain, env var, .env file).
544
+ */
545
+ suppressDefaultRemediation;
546
+ constructor(message = "Invalid API key", reason = "unknown", serverMessage, suppressDefaultRemediation = false) {
547
+ super(message);
548
+ this.name = "AuthenticationError";
549
+ this.reason = reason;
550
+ this.serverMessage = serverMessage;
551
+ this.suppressDefaultRemediation = suppressDefaultRemediation;
552
+ if (Error.captureStackTrace) {
553
+ Error.captureStackTrace(this, _AuthenticationError);
554
+ }
555
+ }
556
+ /**
557
+ * Checks if an error is an AuthenticationError
558
+ * @param error - The error to check
559
+ * @returns True if the error is an AuthenticationError
560
+ */
561
+ static isAuthenticationError(error) {
562
+ return error instanceof _AuthenticationError || error instanceof Error && "isAuthenticationError" in error && error.isAuthenticationError === true;
563
+ }
564
+ };
565
+ }
566
+ });
567
+
568
+ // src/api/http.client.ts
569
+ import { randomUUID } from "crypto";
570
+ var HttpClient;
571
+ var init_http_client = __esm({
572
+ "src/api/http.client.ts"() {
573
+ "use strict";
574
+ init_auth_error();
575
+ HttpClient = class {
576
+ static {
577
+ __name(this, "HttpClient");
578
+ }
579
+ baseUrl;
580
+ /**
581
+ * Creates an instance of HttpClient
582
+ * @param baseUrl - The base URL for all API requests
583
+ */
584
+ constructor(baseUrl) {
585
+ this.baseUrl = baseUrl;
586
+ }
587
+ /**
588
+ * Makes an HTTP request with standardized error handling
589
+ * @param url - The full URL to request
590
+ * @param options - Fetch API request options
591
+ * @returns Promise resolving to an ApiResponse with typed data
592
+ * @private
593
+ */
594
+ async request(url, options = {}) {
595
+ const controller = new AbortController();
596
+ const timeoutId = setTimeout(() => controller.abort(), 3e4);
597
+ try {
598
+ const response = await fetch(url, {
599
+ ...options,
600
+ signal: controller.signal,
601
+ headers: {
602
+ "Content-Type": "application/json",
603
+ ...options.headers
604
+ }
605
+ });
606
+ clearTimeout(timeoutId);
607
+ if (!response.ok) {
608
+ let errorData;
609
+ try {
610
+ errorData = await response.json();
611
+ } catch (jsonError) {
612
+ errorData = {};
613
+ }
614
+ if (response.status === 401) {
615
+ const serverMessage = typeof errorData.message === "string" ? errorData.message : void 0;
616
+ if (serverMessage && /not an admin/i.test(serverMessage)) {
617
+ throw new AuthenticationError(`Access denied for this agent: ${serverMessage}`, "no_agent_access", serverMessage);
618
+ }
619
+ const isExplicitCredential = !!serverMessage && /(invalid|expired|missing|no)\s+(api[\s_-]?key|token|credential)/i.test(serverMessage);
620
+ const isBareAuthRejection = !serverMessage || /^unauthorized$/i.test(serverMessage);
621
+ if (isExplicitCredential || isBareAuthRejection) {
622
+ throw new AuthenticationError("Authentication failed. Your API key may be invalid or expired.", "invalid_credentials", serverMessage);
623
+ }
624
+ throw new AuthenticationError(`Authentication failed: ${serverMessage}`, "unknown", serverMessage);
625
+ }
626
+ if (response.status === 403) {
627
+ const detail = errorData.message || "You do not have permission to access this resource.";
628
+ throw new Error(`Access denied (403): ${detail}
629
+ Check that your API key has access to this agent/organization.`);
630
+ }
631
+ return {
632
+ success: false,
633
+ error: {
634
+ message: errorData.message || `HTTP ${response.status}: ${response.statusText}`,
635
+ statusCode: response.status,
636
+ error: errorData.error,
637
+ ...errorData
638
+ }
639
+ };
640
+ }
641
+ let data;
642
+ try {
643
+ data = await response.json();
644
+ } catch (jsonError) {
645
+ data = {};
646
+ }
647
+ if (typeof data === "object" && data !== null && "success" in data) {
648
+ return data;
649
+ }
650
+ return {
651
+ success: true,
652
+ data
653
+ };
654
+ } catch (error) {
655
+ clearTimeout(timeoutId);
656
+ if (AuthenticationError.isAuthenticationError(error)) {
657
+ throw error;
658
+ }
659
+ if (error instanceof Error && error.message.startsWith("Access denied (403)")) {
660
+ throw error;
661
+ }
662
+ if (error instanceof DOMException && error.name === "AbortError") {
663
+ return {
664
+ success: false,
665
+ error: {
666
+ message: "Request timeout (30s)",
667
+ statusCode: 0
668
+ }
669
+ };
670
+ }
671
+ return {
672
+ success: false,
673
+ error: {
674
+ message: error instanceof Error ? error.message : "Network request failed",
675
+ statusCode: 0
676
+ }
677
+ };
678
+ }
679
+ }
680
+ /**
681
+ * Checks if an HTTP status code is retryable
682
+ * @param statusCode - The HTTP status code (0 for network errors)
683
+ * @returns True if the request should be retried
684
+ * @private
685
+ */
686
+ isRetryableStatus(statusCode) {
687
+ return statusCode === 0 || statusCode === 429 || statusCode >= 500 && statusCode <= 504;
688
+ }
689
+ /**
690
+ * Calculates exponential backoff with full jitter (AWS best practice)
691
+ * @param attempt - The retry attempt number (0-based)
692
+ * @param baseMs - Base delay in milliseconds
693
+ * @param maxMs - Maximum delay cap in milliseconds
694
+ * @returns Delay in milliseconds with random jitter
695
+ * @private
696
+ */
697
+ calculateBackoff(attempt, baseMs = 1e3, maxMs = 15e3) {
698
+ const exponential = Math.min(maxMs, baseMs * Math.pow(2, attempt));
699
+ return Math.max(100, Math.random() * exponential);
700
+ }
701
+ /**
702
+ * Wraps request with retry logic for transient failures
703
+ * @param url - The full URL to request
704
+ * @param options - Fetch API request options
705
+ * @param maxRetries - Maximum number of retry attempts (default 3)
706
+ * @returns Promise resolving to an ApiResponse with typed data
707
+ * @private
708
+ */
709
+ async retryableRequest(url, options = {}, maxRetries = 3) {
710
+ if (options.method === "POST") {
711
+ const headers = options.headers || {};
712
+ if (!headers["X-Idempotency-Key"]) {
713
+ headers["X-Idempotency-Key"] = randomUUID();
714
+ options = {
715
+ ...options,
716
+ headers: {
717
+ ...options.headers,
718
+ ...headers
719
+ }
720
+ };
721
+ }
722
+ }
723
+ let lastResult = null;
724
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
725
+ try {
726
+ const result = await this.request(url, options);
727
+ if (result.success || !result.error || !this.isRetryableStatus(result.error.statusCode || 0)) {
728
+ return result;
729
+ }
730
+ lastResult = result;
731
+ } catch (error) {
732
+ throw error;
733
+ }
734
+ if (attempt < maxRetries) {
735
+ const backoff = this.calculateBackoff(attempt);
736
+ await new Promise((resolve) => setTimeout(resolve, backoff));
737
+ }
738
+ }
739
+ return lastResult;
740
+ }
741
+ /**
742
+ * Performs an HTTP GET request
743
+ * @param url - The relative URL path to request (will be appended to baseUrl)
744
+ * @param headers - Optional HTTP headers to include in the request
745
+ * @returns Promise resolving to an ApiResponse with typed data
746
+ * @protected
747
+ */
748
+ async httpGet(url, headers) {
749
+ return this.retryableRequest(this.baseUrl + url, {
750
+ method: "GET",
751
+ headers
752
+ });
753
+ }
754
+ /**
755
+ * Performs an HTTP POST request
756
+ * @param url - The relative URL path to request (will be appended to baseUrl)
757
+ * @param data - Optional request body data (will be JSON stringified)
758
+ * @param headers - Optional HTTP headers to include in the request
759
+ * @returns Promise resolving to an ApiResponse with typed data
760
+ * @protected
761
+ */
762
+ async httpPost(url, data, headers) {
763
+ return this.retryableRequest(this.baseUrl + url, {
764
+ method: "POST",
765
+ body: data ? JSON.stringify(data) : void 0,
766
+ headers
767
+ });
768
+ }
769
+ /**
770
+ * Performs an HTTP PUT request
771
+ * @param url - The relative URL path to request (will be appended to baseUrl)
772
+ * @param data - Optional request body data (will be JSON stringified)
773
+ * @param headers - Optional HTTP headers to include in the request
774
+ * @returns Promise resolving to an ApiResponse with typed data
775
+ * @protected
776
+ */
777
+ async httpPut(url, data, headers) {
778
+ return this.retryableRequest(this.baseUrl + url, {
779
+ method: "PUT",
780
+ body: data ? JSON.stringify(data) : void 0,
781
+ headers
782
+ });
783
+ }
784
+ /**
785
+ * Performs an HTTP DELETE request
786
+ * @param url - The relative URL path to request (will be appended to baseUrl)
787
+ * @param headers - Optional HTTP headers to include in the request
788
+ * @returns Promise resolving to an ApiResponse with typed data
789
+ * @protected
790
+ */
791
+ async httpDelete(url, headers) {
792
+ return this.retryableRequest(this.baseUrl + url, {
793
+ method: "DELETE",
794
+ headers
795
+ });
796
+ }
797
+ /**
798
+ * Performs an HTTP PATCH request
799
+ * @param url - The relative URL path to request (will be appended to baseUrl)
800
+ * @param data - Optional request body data (will be JSON stringified)
801
+ * @param headers - Optional HTTP headers to include in the request
802
+ * @returns Promise resolving to an ApiResponse with typed data
803
+ * @protected
804
+ */
805
+ async httpPatch(url, data, headers) {
806
+ return this.retryableRequest(this.baseUrl + url, {
807
+ method: "PATCH",
808
+ body: data ? JSON.stringify(data) : void 0,
809
+ headers
810
+ });
811
+ }
812
+ };
813
+ }
814
+ });
815
+
816
+ // src/api/auth.api.service.ts
817
+ var init_auth_api_service = __esm({
818
+ "src/api/auth.api.service.ts"() {
819
+ "use strict";
820
+ init_http_client();
821
+ }
822
+ });
823
+
824
+ // src/services/auth.ts
825
+ import "dotenv/config";
826
+ import { readFileSync, writeFileSync, mkdirSync, unlinkSync } from "fs";
827
+ function getToken() {
828
+ if (process.env.LUA_API_KEY) {
829
+ return process.env.LUA_API_KEY;
830
+ }
831
+ try {
832
+ const token = readFileSync(CREDENTIALS_FILE, "utf8").trim();
833
+ if (token) return token;
834
+ } catch {
835
+ }
836
+ throw new AuthenticationError('No API key found.\n\n Authenticate using one of these methods:\n\n \u279C lua auth configure\n \u279C export LUA_API_KEY="your-api-key-here"\n \u279C Add LUA_API_KEY=... to a .env file\n\n \u{1F511} Get your API key at https://admin.heylua.ai', "invalid_credentials", void 0, true);
837
+ }
838
+ var init_auth = __esm({
839
+ "src/services/auth.ts"() {
840
+ "use strict";
841
+ init_auth_api_service();
842
+ init_constants();
843
+ init_auth_error();
844
+ __name(getToken, "getToken");
845
+ }
846
+ });
847
+
848
+ // src/config/compile.constants.ts
849
+ var COMPILE_DIRS, COMPILE_FILES, SKILL_DEFAULTS, YAML_FORMAT;
850
+ var init_compile_constants = __esm({
851
+ "src/config/compile.constants.ts"() {
852
+ "use strict";
853
+ COMPILE_DIRS = {
854
+ DIST: "dist",
855
+ DIST_V2: "dist-v2",
856
+ LUA: ".lua",
857
+ TOOLS: "tools"
858
+ };
859
+ COMPILE_FILES = {
860
+ DEPLOYMENT_JSON: "deployment.json",
861
+ DEPLOY_JSON: "deploy.json",
862
+ MANIFEST_JSON: "manifest.json",
863
+ INDEX_TS: "index.ts",
864
+ INDEX_JS: "index.js",
865
+ PACKAGE_JSON: "package.json",
866
+ TSCONFIG_JSON: "tsconfig.json",
867
+ LUA_SKILL_YAML: "lua.skill.yaml"
868
+ };
869
+ SKILL_DEFAULTS = {
870
+ NAME: "lua-skill",
871
+ VERSION: "1.0.0",
872
+ DESCRIPTION: "",
873
+ CONTEXT: ""
874
+ };
875
+ YAML_FORMAT = {
876
+ INDENT: 2,
877
+ LINE_WIDTH: -1,
878
+ NO_REFS: true
879
+ };
847
880
  }
848
881
  });
849
882
 
@@ -857,6 +890,7 @@ var init_types = __esm({
857
890
  PrimitiveKind2["SKILL"] = "skill";
858
891
  PrimitiveKind2["JOB"] = "job";
859
892
  PrimitiveKind2["WEBHOOK"] = "webhook";
893
+ PrimitiveKind2["TRIGGER"] = "trigger";
860
894
  PrimitiveKind2["PREPROCESSOR"] = "preprocessor";
861
895
  PrimitiveKind2["POSTPROCESSOR"] = "postprocessor";
862
896
  PrimitiveKind2["MCP_SERVER"] = "mcp-server";
@@ -4607,6 +4641,9 @@ var init_agents_api_service = __esm({
4607
4641
  } : {},
4608
4642
  ...body.threadId !== void 0 ? {
4609
4643
  threadId: body.threadId
4644
+ } : {},
4645
+ ...body.webhookPayload !== void 0 ? {
4646
+ webhookPayload: body.webhookPayload
4610
4647
  } : {}
4611
4648
  };
4612
4649
  }
@@ -4989,6 +5026,30 @@ var init_voice_api_service = __esm({
4989
5026
  });
4990
5027
  }
4991
5028
  /**
5029
+ * Create a voice room + client access token for a custom frontend
5030
+ * (standard livekit-client). The session runs under a synthetic identity;
5031
+ * pass `userId` to scope conversation memory + transcript to your own end
5032
+ * user. Wraps `POST /developer/voice/:agentId/session`.
5033
+ */
5034
+ async createSession(input = {}) {
5035
+ return this.httpPost(`/developer/voice/${this.agentId}/session`, input, {
5036
+ Authorization: `Bearer ${this.apiKey}`
5037
+ });
5038
+ }
5039
+ /**
5040
+ * Sandbox helper: throws on non-success and returns the unwrapped output.
5041
+ */
5042
+ async createSessionForSandbox(input = {}) {
5043
+ const result = await this.createSession(input);
5044
+ if (!result.success) {
5045
+ throw new Error(result.error?.message || "Voice session creation failed");
5046
+ }
5047
+ if (!result.data) {
5048
+ throw new Error("Voice session creation failed: empty response");
5049
+ }
5050
+ return result.data;
5051
+ }
5052
+ /**
4992
5053
  * Sandbox helper: throws on non-success and returns the unwrapped output.
4993
5054
  * Mirrors the shape `AgentsApiService.invokeForSandbox` exposes so the
4994
5055
  * `Voice` namespace in `api-exports.ts` stays a one-liner.
@@ -5007,6 +5068,79 @@ var init_voice_api_service = __esm({
5007
5068
  }
5008
5069
  });
5009
5070
 
5071
+ // src/api/channels-send.api.service.ts
5072
+ var ChannelsSendApiService;
5073
+ var init_channels_send_api_service = __esm({
5074
+ "src/api/channels-send.api.service.ts"() {
5075
+ "use strict";
5076
+ init_http_client();
5077
+ ChannelsSendApiService = class extends HttpClient {
5078
+ static {
5079
+ __name(this, "ChannelsSendApiService");
5080
+ }
5081
+ apiKey;
5082
+ agentId;
5083
+ constructor(baseUrl, apiKey, agentId) {
5084
+ super(baseUrl), this.apiKey = apiKey, this.agentId = agentId;
5085
+ }
5086
+ /** POST /developer/agents/:agentId/channels/send */
5087
+ async send(input) {
5088
+ return this.httpPost(`/developer/agents/${this.agentId}/channels/send`, input, {
5089
+ Authorization: `Bearer ${this.apiKey}`
5090
+ });
5091
+ }
5092
+ /** POST /developer/agents/:agentId/channels/whatsapp/template */
5093
+ async sendWhatsAppTemplate(input) {
5094
+ return this.httpPost(`/developer/agents/${this.agentId}/channels/whatsapp/template`, input, {
5095
+ Authorization: `Bearer ${this.apiKey}`
5096
+ });
5097
+ }
5098
+ /** POST /developer/agents/:agentId/channels/email/send */
5099
+ async sendEmail(input) {
5100
+ return this.httpPost(`/developer/agents/${this.agentId}/channels/email/send`, input, {
5101
+ Authorization: `Bearer ${this.apiKey}`
5102
+ });
5103
+ }
5104
+ /**
5105
+ * Sandbox helper: throws on non-success, returns unwrapped output.
5106
+ * A 200 with `persisted: false` is NOT an error — it passes through.
5107
+ */
5108
+ async sendForSandbox(input) {
5109
+ const result = await this.send(input);
5110
+ if (!result.success) {
5111
+ throw new Error(result.error?.message || "Channel send failed");
5112
+ }
5113
+ if (!result.data) {
5114
+ throw new Error("Channel send failed: empty response");
5115
+ }
5116
+ return result.data;
5117
+ }
5118
+ /** Sandbox helper for WhatsApp template sends. */
5119
+ async sendWhatsAppTemplateForSandbox(input) {
5120
+ const result = await this.sendWhatsAppTemplate(input);
5121
+ if (!result.success) {
5122
+ throw new Error(result.error?.message || "WhatsApp template send failed");
5123
+ }
5124
+ if (!result.data) {
5125
+ throw new Error("WhatsApp template send failed: empty response");
5126
+ }
5127
+ return result.data;
5128
+ }
5129
+ /** Sandbox helper for email sends. */
5130
+ async sendEmailForSandbox(input) {
5131
+ const result = await this.sendEmail(input);
5132
+ if (!result.success) {
5133
+ throw new Error(result.error?.message || "Email send failed");
5134
+ }
5135
+ if (!result.data) {
5136
+ throw new Error("Email send failed: empty response");
5137
+ }
5138
+ return result.data;
5139
+ }
5140
+ };
5141
+ }
5142
+ });
5143
+
5010
5144
  // src/api/device.api.service.ts
5011
5145
  var device_api_service_exports = {};
5012
5146
  __export(device_api_service_exports, {
@@ -5099,6 +5233,7 @@ __export(lazy_instances_exports, {
5099
5233
  getAiInstance: () => getAiInstance,
5100
5234
  getBasketsInstance: () => getBasketsInstance,
5101
5235
  getCdnInstance: () => getCdnInstance,
5236
+ getChannelsSendInstance: () => getChannelsSendInstance,
5102
5237
  getDataInstance: () => getDataInstance,
5103
5238
  getDeveloperInstance: () => getDeveloperInstance,
5104
5239
  getDeviceInstance: () => getDeviceInstance,
@@ -5209,6 +5344,13 @@ async function getVoiceInstance() {
5209
5344
  }
5210
5345
  return _voiceInstance;
5211
5346
  }
5347
+ async function getChannelsSendInstance() {
5348
+ if (!_channelsSendInstance) {
5349
+ const creds = await getCredentials();
5350
+ _channelsSendInstance = new ChannelsSendApiService(BASE_URLS.API, creds.apiKey, creds.agentId);
5351
+ }
5352
+ return _channelsSendInstance;
5353
+ }
5212
5354
  function clearAllInstances() {
5213
5355
  _userInstance = null;
5214
5356
  _dataInstance = null;
@@ -5223,8 +5365,9 @@ function clearAllInstances() {
5223
5365
  _cdnInstance = null;
5224
5366
  _developerInstance = null;
5225
5367
  _voiceInstance = null;
5368
+ _channelsSendInstance = null;
5226
5369
  }
5227
- var _userInstance, _dataInstance, _productsInstance, _basketsInstance, _orderInstance, _webhookInstance, _jobInstance, _aiInstance, _agentsInstance, _whatsAppTemplatesInstance, _cdnInstance, _developerInstance, _voiceInstance, _deviceInstance;
5370
+ var _userInstance, _dataInstance, _productsInstance, _basketsInstance, _orderInstance, _webhookInstance, _jobInstance, _aiInstance, _agentsInstance, _whatsAppTemplatesInstance, _cdnInstance, _developerInstance, _voiceInstance, _channelsSendInstance, _deviceInstance;
5228
5371
  var init_lazy_instances = __esm({
5229
5372
  "src/api/lazy-instances.ts"() {
5230
5373
  "use strict";
@@ -5243,6 +5386,7 @@ var init_lazy_instances = __esm({
5243
5386
  init_cdn_api_service();
5244
5387
  init_developer_api_service();
5245
5388
  init_voice_api_service();
5389
+ init_channels_send_api_service();
5246
5390
  _userInstance = null;
5247
5391
  _dataInstance = null;
5248
5392
  _productsInstance = null;
@@ -5256,6 +5400,7 @@ var init_lazy_instances = __esm({
5256
5400
  _cdnInstance = null;
5257
5401
  _developerInstance = null;
5258
5402
  _voiceInstance = null;
5403
+ _channelsSendInstance = null;
5259
5404
  __name(getUserInstance, "getUserInstance");
5260
5405
  __name(getDataInstance, "getDataInstance");
5261
5406
  __name(getProductsInstance, "getProductsInstance");
@@ -5271,6 +5416,7 @@ var init_lazy_instances = __esm({
5271
5416
  __name(getDeviceInstance, "getDeviceInstance");
5272
5417
  __name(getDeveloperInstance, "getDeveloperInstance");
5273
5418
  __name(getVoiceInstance, "getVoiceInstance");
5419
+ __name(getChannelsSendInstance, "getChannelsSendInstance");
5274
5420
  __name(clearAllInstances, "clearAllInstances");
5275
5421
  }
5276
5422
  });
@@ -5557,6 +5703,39 @@ var LuaWebhook = class {
5557
5703
  return this.executeFunction(event);
5558
5704
  }
5559
5705
  };
5706
+ var LuaTrigger = class {
5707
+ static {
5708
+ __name(this, "LuaTrigger");
5709
+ }
5710
+ name;
5711
+ description;
5712
+ source;
5713
+ inputSchema;
5714
+ verify;
5715
+ filter;
5716
+ transform;
5717
+ constructor(config) {
5718
+ if (!config.name || !config.name.trim()) {
5719
+ throw new Error("LuaTrigger requires a non-empty `name` (used as the server-side identifier).");
5720
+ }
5721
+ if (!config.verify && !config.filter && !config.transform) {
5722
+ throw new Error("LuaTrigger requires at least one of verify, filter, or transform.");
5723
+ }
5724
+ this.name = config.name;
5725
+ this.description = config.description;
5726
+ this.source = config.source ?? "webhook";
5727
+ this.inputSchema = config.inputSchema;
5728
+ this.verify = config.verify;
5729
+ this.filter = config.filter;
5730
+ this.transform = config.transform;
5731
+ }
5732
+ getName() {
5733
+ return this.name;
5734
+ }
5735
+ getDescription() {
5736
+ return this.description;
5737
+ }
5738
+ };
5560
5739
  var PreProcessor = class {
5561
5740
  static {
5562
5741
  __name(this, "PreProcessor");
@@ -5712,6 +5891,7 @@ var LuaAgent = class {
5712
5891
  modelSettings;
5713
5892
  skills;
5714
5893
  webhooks;
5894
+ triggers;
5715
5895
  jobs;
5716
5896
  preProcessors;
5717
5897
  postProcessors;
@@ -5752,6 +5932,7 @@ var LuaAgent = class {
5752
5932
  }
5753
5933
  this.skills = config.skills || [];
5754
5934
  this.webhooks = config.webhooks || [];
5935
+ this.triggers = config.triggers || [];
5755
5936
  this.jobs = config.jobs || [];
5756
5937
  this.preProcessors = config.preProcessors || [];
5757
5938
  this.postProcessors = config.postProcessors || [];
@@ -5780,6 +5961,9 @@ var LuaAgent = class {
5780
5961
  getWebhooks() {
5781
5962
  return this.webhooks;
5782
5963
  }
5964
+ getTriggers() {
5965
+ return this.triggers;
5966
+ }
5783
5967
  getJobs() {
5784
5968
  return this.jobs;
5785
5969
  }
@@ -5879,6 +6063,7 @@ var LuaVoice = class {
5879
6063
  preemptiveGeneration;
5880
6064
  interruption;
5881
6065
  sttLanguage;
6066
+ excludeTools;
5882
6067
  tools;
5883
6068
  onEnter;
5884
6069
  onUserTurnCompleted;
@@ -5901,6 +6086,7 @@ var LuaVoice = class {
5901
6086
  this.preemptiveGeneration = config.preemptiveGeneration;
5902
6087
  this.interruption = config.interruption;
5903
6088
  this.sttLanguage = config.sttLanguage;
6089
+ this.excludeTools = config.excludeTools;
5904
6090
  this.tools = Object.freeze([
5905
6091
  ...config.tools ?? []
5906
6092
  ]);
@@ -5915,6 +6101,7 @@ function defineVoice(config) {
5915
6101
  __name(defineVoice, "defineVoice");
5916
6102
 
5917
6103
  // src/api-exports.ts
6104
+ init_dist();
5918
6105
  init_baskets();
5919
6106
 
5920
6107
  // src/interfaces/orders.ts
@@ -6398,6 +6585,32 @@ var Voice = {
6398
6585
  const { getVoiceInstance: getVoiceInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
6399
6586
  const voice = await getVoiceInstance2();
6400
6587
  return voice.dispatchForSandbox(input);
6588
+ },
6589
+ async createSession(input) {
6590
+ const { getVoiceInstance: getVoiceInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
6591
+ const voice = await getVoiceInstance2();
6592
+ return voice.createSessionForSandbox(input ?? {});
6593
+ }
6594
+ };
6595
+ var Channels = {
6596
+ async send(input) {
6597
+ const { getChannelsSendInstance: getChannelsSendInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
6598
+ const channels = await getChannelsSendInstance2();
6599
+ return channels.sendForSandbox(input);
6600
+ },
6601
+ whatsapp: {
6602
+ async sendTemplate(input) {
6603
+ const { getChannelsSendInstance: getChannelsSendInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
6604
+ const channels = await getChannelsSendInstance2();
6605
+ return channels.sendWhatsAppTemplateForSandbox(input);
6606
+ }
6607
+ },
6608
+ email: {
6609
+ async send(input) {
6610
+ const { getChannelsSendInstance: getChannelsSendInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
6611
+ const channels = await getChannelsSendInstance2();
6612
+ return channels.sendEmailForSandbox(input);
6613
+ }
6401
6614
  }
6402
6615
  };
6403
6616
  var Templates = {
@@ -6531,6 +6744,10 @@ function defineDeviceTrigger(config) {
6531
6744
  return new LuaDeviceTrigger(config);
6532
6745
  }
6533
6746
  __name(defineDeviceTrigger, "defineDeviceTrigger");
6747
+ function defineTrigger(config) {
6748
+ return new LuaTrigger(config);
6749
+ }
6750
+ __name(defineTrigger, "defineTrigger");
6534
6751
  export {
6535
6752
  AI,
6536
6753
  Agents,
@@ -6538,6 +6755,8 @@ export {
6538
6755
  BasketStatus,
6539
6756
  Baskets,
6540
6757
  CDN,
6758
+ CHANNEL_SEND_CHANNELS,
6759
+ Channels,
6541
6760
  Data,
6542
6761
  DataEntryInstance,
6543
6762
  JobInstance,
@@ -6551,6 +6770,7 @@ export {
6551
6770
  PostProcessor as LuaPostprocessor,
6552
6771
  PreProcessor as LuaPreprocessor,
6553
6772
  LuaSkill,
6773
+ LuaTrigger,
6554
6774
  LuaVoice,
6555
6775
  LuaVoiceTool,
6556
6776
  LuaWebhook,
@@ -6568,6 +6788,7 @@ export {
6568
6788
  Voice,
6569
6789
  defineDevice,
6570
6790
  defineDeviceTrigger,
6791
+ defineTrigger,
6571
6792
  defineVoice,
6572
6793
  env
6573
6794
  };