lua-cli 3.17.6 → 3.20.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.
- package/dist/api-exports.d.ts +681 -49
- package/dist/api-exports.js +1258 -521
- package/dist/api-exports.js.map +1 -1
- package/dist/index.js +2925 -486
- package/dist/index.js.map +1 -1
- package/dist/voice/test/index.d.ts +58 -37
- package/dist/zod-runtime.mjs +2 -2
- package/docs/API_REFERENCE.md +48 -1
- package/docs/README.md +2 -2
- package/package.json +2 -2
- package/template/package.json +1 -1
package/dist/api-exports.js
CHANGED
|
@@ -9,537 +9,318 @@ var __export = (target, all) => {
|
|
|
9
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
BasketStatus2["ABANDONED"] = "abandoned";
|
|
21
|
-
BasketStatus2["EXPIRED"] = "expired";
|
|
22
|
-
return BasketStatus2;
|
|
23
|
-
})({});
|
|
12
|
+
// ../shared-types/dist/index.mjs
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
function isPersonaTextObject(value) {
|
|
15
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
16
|
+
const obj = value;
|
|
17
|
+
for (const k of Object.keys(obj)) {
|
|
18
|
+
if (k !== "base" && k !== "voice" && k !== "text") return false;
|
|
19
|
+
if (obj[k] !== void 0 && typeof obj[k] !== "string") return false;
|
|
24
20
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
function flattenPersonaText(input, isVoice = false) {
|
|
24
|
+
if (input == null) return "";
|
|
25
|
+
if (typeof input === "string") return input;
|
|
26
|
+
const parts = [];
|
|
27
|
+
if (input.base) parts.push(input.base);
|
|
28
|
+
const channelText = isVoice ? input.voice : input.text;
|
|
29
|
+
if (channelText) parts.push(channelText);
|
|
30
|
+
return parts.join("\n\n");
|
|
31
|
+
}
|
|
32
|
+
function flattenPersonaTextAll(input) {
|
|
33
|
+
if (input == null) return "";
|
|
34
|
+
if (typeof input === "string") return input;
|
|
35
|
+
const parts = [];
|
|
36
|
+
if (input.base) parts.push(input.base);
|
|
37
|
+
if (input.voice) parts.push(input.voice);
|
|
38
|
+
if (input.text) parts.push(input.text);
|
|
39
|
+
return parts.join("\n\n");
|
|
40
|
+
}
|
|
41
|
+
function hasPersonaTextContent(input) {
|
|
42
|
+
if (input == null) return false;
|
|
43
|
+
if (typeof input === "string") return input.trim().length > 0;
|
|
44
|
+
return Boolean(input.base?.trim() || input.voice?.trim() || input.text?.trim());
|
|
45
|
+
}
|
|
46
|
+
function personaToLiteral(persona) {
|
|
47
|
+
const formatValue = /* @__PURE__ */ __name2((v) => {
|
|
48
|
+
if (v.includes("\n")) {
|
|
49
|
+
return "`" + v.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$") + "`";
|
|
50
|
+
}
|
|
51
|
+
return '"' + v.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"';
|
|
52
|
+
}, "formatValue");
|
|
53
|
+
if (typeof persona === "string") return formatValue(persona);
|
|
54
|
+
const parts = [];
|
|
55
|
+
if (persona.base !== void 0) parts.push(`base: ${formatValue(persona.base)}`);
|
|
56
|
+
if (persona.voice !== void 0) parts.push(`voice: ${formatValue(persona.voice)}`);
|
|
57
|
+
if (persona.text !== void 0) parts.push(`text: ${formatValue(persona.text)}`);
|
|
58
|
+
return `{ ${parts.join(", ")} }`;
|
|
59
|
+
}
|
|
60
|
+
function aiGenerateInputFromSimplified(prompt, content) {
|
|
61
|
+
if (content === void 0) {
|
|
62
|
+
return {
|
|
63
|
+
prompt
|
|
44
64
|
};
|
|
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
65
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"use strict";
|
|
56
|
-
AuthenticationError = class _AuthenticationError extends Error {
|
|
57
|
-
static {
|
|
58
|
-
__name(this, "AuthenticationError");
|
|
66
|
+
return {
|
|
67
|
+
system: prompt,
|
|
68
|
+
messages: [
|
|
69
|
+
{
|
|
70
|
+
role: "user",
|
|
71
|
+
content
|
|
59
72
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
73
|
+
]
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function isAllowedReviewableExecuteTool(tool) {
|
|
77
|
+
return REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST.includes(tool);
|
|
78
|
+
}
|
|
79
|
+
function isReviewableMcpSendTool(tool) {
|
|
80
|
+
return tool.length > REVIEWABLE_MCP_SEND_TOOL_SUFFIX.length && tool.endsWith(REVIEWABLE_MCP_SEND_TOOL_SUFFIX);
|
|
81
|
+
}
|
|
82
|
+
function isReviewableExecuteTool(tool) {
|
|
83
|
+
return isAllowedReviewableExecuteTool(tool) || isReviewableMcpSendTool(tool);
|
|
84
|
+
}
|
|
85
|
+
function isInteractiveChannel(channel) {
|
|
86
|
+
if (!channel) return true;
|
|
87
|
+
return !NON_INTERACTIVE_CHANNELS.includes(channel);
|
|
88
|
+
}
|
|
89
|
+
function isInteractiveTurn(turn) {
|
|
90
|
+
if (typeof turn.interactive === "boolean") return turn.interactive;
|
|
91
|
+
return isInteractiveChannel(turn.channel);
|
|
92
|
+
}
|
|
93
|
+
function removeNavigateBlock(input) {
|
|
94
|
+
return input.replace(/::: navigate[\s\S]*?:::/g, "").trim();
|
|
95
|
+
}
|
|
96
|
+
function transformChatHistoryContentParts(parts) {
|
|
97
|
+
const content = [];
|
|
98
|
+
for (const rawPart of parts ?? []) {
|
|
99
|
+
const part = rawPart;
|
|
100
|
+
if (part?.type === "reasoning") {
|
|
101
|
+
const detailsText = Array.isArray(part.details) ? part.details.filter((d) => d?.type === "text" && typeof d.text === "string").map((d) => d.text).join("") : "";
|
|
102
|
+
const reasoningText = [
|
|
103
|
+
part.reasoning,
|
|
104
|
+
detailsText,
|
|
105
|
+
part.text
|
|
106
|
+
].find((v) => typeof v === "string" && v.trim().length > 0) ?? "";
|
|
107
|
+
if (reasoningText) content.push({
|
|
108
|
+
type: "reasoning",
|
|
109
|
+
text: reasoningText
|
|
110
|
+
});
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (part?.type === "tool-invocation") {
|
|
114
|
+
const inv = part.toolInvocation;
|
|
115
|
+
if (typeof inv?.toolName === "string" && inv.toolName.length > 0) {
|
|
116
|
+
content.push({
|
|
117
|
+
type: "tool",
|
|
118
|
+
toolName: inv.toolName,
|
|
119
|
+
toolCallId: inv.toolCallId,
|
|
120
|
+
input: inv.args,
|
|
121
|
+
output: inv.result,
|
|
122
|
+
toolState: inv.state
|
|
123
|
+
});
|
|
81
124
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (part?.type === "source") {
|
|
128
|
+
const src = part.source;
|
|
129
|
+
if (src?.sourceType === "document") {
|
|
130
|
+
content.push({
|
|
131
|
+
type: "source-document",
|
|
132
|
+
sourceId: src.id,
|
|
133
|
+
mediaType: src.mediaType,
|
|
134
|
+
title: src.title,
|
|
135
|
+
filename: src.filename,
|
|
136
|
+
providerMetadata: src.providerMetadata
|
|
137
|
+
});
|
|
138
|
+
} else if (typeof src?.url === "string" && src.url.length > 0) {
|
|
139
|
+
content.push({
|
|
140
|
+
type: "source-url",
|
|
141
|
+
sourceId: src.id,
|
|
142
|
+
url: src.url,
|
|
143
|
+
title: src.title,
|
|
144
|
+
providerMetadata: src.providerMetadata
|
|
145
|
+
});
|
|
89
146
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
HttpClient = class {
|
|
102
|
-
static {
|
|
103
|
-
__name(this, "HttpClient");
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (part?.type === "source-url") {
|
|
150
|
+
if (typeof part.url === "string" && part.url.length > 0) {
|
|
151
|
+
content.push({
|
|
152
|
+
type: "source-url",
|
|
153
|
+
sourceId: part.sourceId,
|
|
154
|
+
url: part.url,
|
|
155
|
+
title: part.title,
|
|
156
|
+
providerMetadata: part.providerMetadata
|
|
157
|
+
});
|
|
104
158
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (part?.type === "source-document") {
|
|
162
|
+
content.push({
|
|
163
|
+
type: "source-document",
|
|
164
|
+
sourceId: part.sourceId,
|
|
165
|
+
mediaType: part.mediaType,
|
|
166
|
+
title: part.title,
|
|
167
|
+
filename: part.filename,
|
|
168
|
+
providerMetadata: part.providerMetadata
|
|
169
|
+
});
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
if (typeof part?.type === "string" && part.type.startsWith("data-lua-")) {
|
|
173
|
+
content.push({
|
|
174
|
+
type: part.type,
|
|
175
|
+
payload: rawPart.data
|
|
176
|
+
});
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
if (part?.type !== "text" && part?.type !== "file") continue;
|
|
180
|
+
if (part.type === "text" && typeof part.text === "string") {
|
|
181
|
+
const rawText = part.text || "";
|
|
182
|
+
if (rawText.includes("::: hide")) continue;
|
|
183
|
+
const audioMatch = rawText.match(/::: audio\s*!\[(.*?)\]\((.*?)\)\s*:::/);
|
|
184
|
+
const videoMatch = rawText.match(/::: video\s*!\[(.*?)\]\((.*?)\)\s*:::/);
|
|
185
|
+
if (audioMatch) {
|
|
186
|
+
content.push({
|
|
187
|
+
type: "audio",
|
|
188
|
+
data: audioMatch[2],
|
|
189
|
+
mediaType: audioMatch[1]
|
|
190
|
+
});
|
|
191
|
+
} else if (videoMatch) {
|
|
192
|
+
content.push({
|
|
193
|
+
type: "video",
|
|
194
|
+
video: videoMatch[2],
|
|
195
|
+
mediaType: videoMatch[1]
|
|
196
|
+
});
|
|
197
|
+
} else {
|
|
198
|
+
let text = rawText.replace(/\\\\\\n/g, "\n");
|
|
199
|
+
text = removeNavigateBlock(text);
|
|
200
|
+
content.push({
|
|
201
|
+
type: "text",
|
|
202
|
+
text
|
|
203
|
+
});
|
|
112
204
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
|
205
|
+
} else if (part.type === "file") {
|
|
206
|
+
const mediaType = part.mimeType || "";
|
|
207
|
+
if (mediaType.startsWith("image/")) {
|
|
208
|
+
content.push({
|
|
209
|
+
type: "image",
|
|
210
|
+
image: part.data,
|
|
211
|
+
mediaType
|
|
293
212
|
});
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
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
|
|
213
|
+
} else if (mediaType.startsWith("video/")) {
|
|
214
|
+
content.push({
|
|
215
|
+
type: "video",
|
|
216
|
+
video: part.data,
|
|
217
|
+
mediaType
|
|
308
218
|
});
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
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
|
|
219
|
+
} else if (mediaType.startsWith("audio/")) {
|
|
220
|
+
content.push({
|
|
221
|
+
type: "audio",
|
|
222
|
+
data: part.data,
|
|
223
|
+
mediaType
|
|
321
224
|
});
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
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
|
|
225
|
+
} else {
|
|
226
|
+
content.push({
|
|
227
|
+
type: "file",
|
|
228
|
+
data: part.data,
|
|
229
|
+
mediaType
|
|
336
230
|
});
|
|
337
231
|
}
|
|
338
|
-
}
|
|
232
|
+
}
|
|
339
233
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
234
|
+
return content;
|
|
235
|
+
}
|
|
236
|
+
function isSyntheticSideRow(id) {
|
|
237
|
+
return id.startsWith(SCREENSHOT_MESSAGE_ID_PREFIX) || id.startsWith(RICH_PARTS_MESSAGE_ID_PREFIX);
|
|
238
|
+
}
|
|
239
|
+
function mergeRichPartMirrorMessages(messages, sameTurnGroup) {
|
|
240
|
+
const merged = [];
|
|
241
|
+
for (const message of messages) {
|
|
242
|
+
if (message.role === "assistant" && message.id.startsWith(RICH_PARTS_MESSAGE_ID_PREFIX)) {
|
|
243
|
+
let folded = false;
|
|
244
|
+
for (let i = merged.length - 1; i >= 0; i--) {
|
|
245
|
+
const target = merged[i];
|
|
246
|
+
if (sameTurnGroup && !sameTurnGroup(target, message)) continue;
|
|
247
|
+
if (isSyntheticSideRow(target.id)) continue;
|
|
248
|
+
if (target.role !== "assistant") break;
|
|
249
|
+
const seen = /* @__PURE__ */ new Set();
|
|
250
|
+
for (const part of target.content) {
|
|
251
|
+
for (const key of citationDedupeKeys(part)) seen.add(key);
|
|
252
|
+
}
|
|
253
|
+
const incoming = [];
|
|
254
|
+
for (const part of message.content) {
|
|
255
|
+
const keys = citationDedupeKeys(part);
|
|
256
|
+
if (keys.length > 0 && keys.some((k) => seen.has(k))) continue;
|
|
257
|
+
for (const key of keys) seen.add(key);
|
|
258
|
+
incoming.push(part);
|
|
259
|
+
}
|
|
260
|
+
merged[i] = {
|
|
261
|
+
...target,
|
|
262
|
+
content: [
|
|
263
|
+
...target.content,
|
|
264
|
+
...incoming
|
|
265
|
+
]
|
|
266
|
+
};
|
|
267
|
+
folded = true;
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
if (folded) continue;
|
|
271
|
+
}
|
|
272
|
+
merged.push(message);
|
|
347
273
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
if (
|
|
355
|
-
|
|
274
|
+
return merged;
|
|
275
|
+
}
|
|
276
|
+
function citationDedupeKeys(part) {
|
|
277
|
+
if (part.type !== "source-url" && part.type !== "source-document") return [];
|
|
278
|
+
const keys = [];
|
|
279
|
+
if (typeof part.sourceId === "string" && part.sourceId.length > 0) keys.push(`id:${part.sourceId}`);
|
|
280
|
+
if (typeof part.url === "string" && part.url.length > 0) keys.push(`url:${part.url}`);
|
|
281
|
+
return keys;
|
|
282
|
+
}
|
|
283
|
+
function foldRichPartsIntoMessages(messages, records, makeMessage, sameTurnGroup) {
|
|
284
|
+
if (messages.length === 0 || records.length === 0) return messages;
|
|
285
|
+
const messageTime = /* @__PURE__ */ __name2((m) => m.createdAt ? new Date(m.createdAt).getTime() : Number.NEGATIVE_INFINITY, "messageTime");
|
|
286
|
+
const finiteTimes = messages.map(messageTime).filter(Number.isFinite);
|
|
287
|
+
const oldest = finiteTimes.length > 0 ? Math.min(...finiteTimes) : Number.NEGATIVE_INFINITY;
|
|
288
|
+
const synthetic = [];
|
|
289
|
+
for (const record of records) {
|
|
290
|
+
const time = new Date(record.createdAt).getTime();
|
|
291
|
+
if (!Number.isFinite(time) || time < oldest) continue;
|
|
292
|
+
const content = transformChatHistoryContentParts(record.parts);
|
|
293
|
+
if (content.length === 0) continue;
|
|
294
|
+
synthetic.push({
|
|
295
|
+
time,
|
|
296
|
+
message: makeMessage({
|
|
297
|
+
id: `${RICH_PARTS_MESSAGE_ID_PREFIX}${record.threadId}:${record.messageId}`,
|
|
298
|
+
role: "assistant",
|
|
299
|
+
createdAt: new Date(time).toISOString(),
|
|
300
|
+
content
|
|
301
|
+
}, record)
|
|
302
|
+
});
|
|
356
303
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
304
|
+
if (synthetic.length === 0) return messages;
|
|
305
|
+
synthetic.sort((a, b) => a.time - b.time);
|
|
306
|
+
const combined = [];
|
|
307
|
+
let next = 0;
|
|
308
|
+
for (const message of messages) {
|
|
309
|
+
const time = messageTime(message);
|
|
310
|
+
while (next < synthetic.length && synthetic[next].time < time) {
|
|
311
|
+
combined.push(synthetic[next++].message);
|
|
312
|
+
}
|
|
313
|
+
combined.push(message);
|
|
361
314
|
}
|
|
362
|
-
|
|
315
|
+
while (next < synthetic.length) combined.push(synthetic[next++].message);
|
|
316
|
+
return mergeRichPartMirrorMessages(combined, sameTurnGroup);
|
|
363
317
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
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
|
-
// ../shared-types/dist/index.mjs
|
|
410
|
-
import { z } from "zod";
|
|
411
|
-
function isPersonaTextObject(value) {
|
|
412
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
413
|
-
const obj = value;
|
|
414
|
-
for (const k of Object.keys(obj)) {
|
|
415
|
-
if (k !== "base" && k !== "voice" && k !== "text") return false;
|
|
416
|
-
if (obj[k] !== void 0 && typeof obj[k] !== "string") return false;
|
|
417
|
-
}
|
|
418
|
-
return true;
|
|
419
|
-
}
|
|
420
|
-
function flattenPersonaText(input, isVoice = false) {
|
|
421
|
-
if (input == null) return "";
|
|
422
|
-
if (typeof input === "string") return input;
|
|
423
|
-
const parts = [];
|
|
424
|
-
if (input.base) parts.push(input.base);
|
|
425
|
-
const channelText = isVoice ? input.voice : input.text;
|
|
426
|
-
if (channelText) parts.push(channelText);
|
|
427
|
-
return parts.join("\n\n");
|
|
428
|
-
}
|
|
429
|
-
function flattenPersonaTextAll(input) {
|
|
430
|
-
if (input == null) return "";
|
|
431
|
-
if (typeof input === "string") return input;
|
|
432
|
-
const parts = [];
|
|
433
|
-
if (input.base) parts.push(input.base);
|
|
434
|
-
if (input.voice) parts.push(input.voice);
|
|
435
|
-
if (input.text) parts.push(input.text);
|
|
436
|
-
return parts.join("\n\n");
|
|
437
|
-
}
|
|
438
|
-
function hasPersonaTextContent(input) {
|
|
439
|
-
if (input == null) return false;
|
|
440
|
-
if (typeof input === "string") return input.trim().length > 0;
|
|
441
|
-
return Boolean(input.base?.trim() || input.voice?.trim() || input.text?.trim());
|
|
442
|
-
}
|
|
443
|
-
function personaToLiteral(persona) {
|
|
444
|
-
const formatValue = /* @__PURE__ */ __name2((v) => {
|
|
445
|
-
if (v.includes("\n")) {
|
|
446
|
-
return "`" + v.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$") + "`";
|
|
447
|
-
}
|
|
448
|
-
return '"' + v.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"';
|
|
449
|
-
}, "formatValue");
|
|
450
|
-
if (typeof persona === "string") return formatValue(persona);
|
|
451
|
-
const parts = [];
|
|
452
|
-
if (persona.base !== void 0) parts.push(`base: ${formatValue(persona.base)}`);
|
|
453
|
-
if (persona.voice !== void 0) parts.push(`voice: ${formatValue(persona.voice)}`);
|
|
454
|
-
if (persona.text !== void 0) parts.push(`text: ${formatValue(persona.text)}`);
|
|
455
|
-
return `{ ${parts.join(", ")} }`;
|
|
456
|
-
}
|
|
457
|
-
function aiGenerateInputFromSimplified(prompt, content) {
|
|
458
|
-
if (content === void 0) {
|
|
459
|
-
return {
|
|
460
|
-
prompt
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
|
-
return {
|
|
464
|
-
system: prompt,
|
|
465
|
-
messages: [
|
|
466
|
-
{
|
|
467
|
-
role: "user",
|
|
468
|
-
content
|
|
469
|
-
}
|
|
470
|
-
]
|
|
471
|
-
};
|
|
472
|
-
}
|
|
473
|
-
function removeNavigateBlock(input) {
|
|
474
|
-
return input.replace(/::: navigate[\s\S]*?:::/g, "").trim();
|
|
475
|
-
}
|
|
476
|
-
function transformChatHistoryContentParts(parts) {
|
|
477
|
-
const content = [];
|
|
478
|
-
for (const rawPart of parts ?? []) {
|
|
479
|
-
const part = rawPart;
|
|
480
|
-
if (part?.type !== "text" && part?.type !== "file") continue;
|
|
481
|
-
if (part.type === "text" && typeof part.text === "string") {
|
|
482
|
-
const rawText = part.text || "";
|
|
483
|
-
if (rawText.includes("::: hide")) continue;
|
|
484
|
-
const audioMatch = rawText.match(/::: audio\s*!\[(.*?)\]\((.*?)\)\s*:::/);
|
|
485
|
-
const videoMatch = rawText.match(/::: video\s*!\[(.*?)\]\((.*?)\)\s*:::/);
|
|
486
|
-
if (audioMatch) {
|
|
487
|
-
content.push({
|
|
488
|
-
type: "audio",
|
|
489
|
-
data: audioMatch[2],
|
|
490
|
-
mediaType: audioMatch[1]
|
|
491
|
-
});
|
|
492
|
-
} else if (videoMatch) {
|
|
493
|
-
content.push({
|
|
494
|
-
type: "video",
|
|
495
|
-
video: videoMatch[2],
|
|
496
|
-
mediaType: videoMatch[1]
|
|
497
|
-
});
|
|
498
|
-
} else {
|
|
499
|
-
let text = rawText.replace(/\\\\\\n/g, "\n");
|
|
500
|
-
text = removeNavigateBlock(text);
|
|
501
|
-
content.push({
|
|
502
|
-
type: "text",
|
|
503
|
-
text
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
|
-
} else if (part.type === "file") {
|
|
507
|
-
const mediaType = part.mimeType || "";
|
|
508
|
-
if (mediaType.startsWith("image/")) {
|
|
509
|
-
content.push({
|
|
510
|
-
type: "image",
|
|
511
|
-
image: part.data,
|
|
512
|
-
mediaType
|
|
513
|
-
});
|
|
514
|
-
} else if (mediaType.startsWith("video/")) {
|
|
515
|
-
content.push({
|
|
516
|
-
type: "video",
|
|
517
|
-
video: part.data,
|
|
518
|
-
mediaType
|
|
519
|
-
});
|
|
520
|
-
} else if (mediaType.startsWith("audio/")) {
|
|
521
|
-
content.push({
|
|
522
|
-
type: "audio",
|
|
523
|
-
data: part.data,
|
|
524
|
-
mediaType
|
|
525
|
-
});
|
|
526
|
-
} else {
|
|
527
|
-
content.push({
|
|
528
|
-
type: "file",
|
|
529
|
-
data: part.data,
|
|
530
|
-
mediaType
|
|
531
|
-
});
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
return content;
|
|
536
|
-
}
|
|
537
|
-
function buildDefaultPersona(agentName) {
|
|
538
|
-
return DEFAULT_PERSONA_GUIDE.replace(AGENT_NAME_TOKEN, () => agentName || "My Agent");
|
|
539
|
-
}
|
|
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;
|
|
541
|
-
var init_dist = __esm({
|
|
542
|
-
"../shared-types/dist/index.mjs"() {
|
|
318
|
+
function buildDefaultPersona(agentName) {
|
|
319
|
+
return DEFAULT_PERSONA_GUIDE.replace(AGENT_NAME_TOKEN, () => agentName || "My Agent");
|
|
320
|
+
}
|
|
321
|
+
var __defProp2, __name2, CHANNEL_SEND_CHANNELS, REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST, REVIEWABLE_MCP_SEND_TOOL_SUFFIX, NON_INTERACTIVE_CHANNELS, RICH_PARTS_MESSAGE_ID_PREFIX, SCREENSHOT_MESSAGE_ID_PREFIX, BROWSER_COMMANDS, BROWSER_COMMAND_NAMES, REASONING_EFFORT_VALUES, AGENT_NAME_TOKEN, DEFAULT_PERSONA_GUIDE, VoiceNameSchema, PluginProviderSchema, RealtimeProviderSchema, PluginClassSchema, ModelDescriptorSchema, InferenceModelSchema, PluginModelSchema, RealtimeModelSchema, LuaVoiceModelSchema, TurnDetectionSchema, InterruptionSchema, BuiltinAudioClipSchema, AudioConfigSchema, BackgroundAudioEntrySchema, BackgroundAudioSchema, LuaVoiceConfigInnerSchema, LuaVoiceConfigSchema, LuaVoiceRefSchema;
|
|
322
|
+
var init_dist = __esm({
|
|
323
|
+
"../shared-types/dist/index.mjs"() {
|
|
543
324
|
"use strict";
|
|
544
325
|
__defProp2 = Object.defineProperty;
|
|
545
326
|
__name2 = /* @__PURE__ */ __name((target, value) => __defProp2(target, "name", { value, configurable: true }), "__name");
|
|
@@ -555,10 +336,270 @@ var init_dist = __esm({
|
|
|
555
336
|
__name2(personaToLiteral, "personaToLiteral");
|
|
556
337
|
__name(aiGenerateInputFromSimplified, "aiGenerateInputFromSimplified");
|
|
557
338
|
__name2(aiGenerateInputFromSimplified, "aiGenerateInputFromSimplified");
|
|
339
|
+
CHANNEL_SEND_CHANNELS = [
|
|
340
|
+
"whatsapp",
|
|
341
|
+
"sms",
|
|
342
|
+
"email",
|
|
343
|
+
"webchat",
|
|
344
|
+
"teams",
|
|
345
|
+
"instagram",
|
|
346
|
+
"messenger"
|
|
347
|
+
];
|
|
348
|
+
REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST = [
|
|
349
|
+
"sendChannelMessage",
|
|
350
|
+
"sendWhatsappTemplate",
|
|
351
|
+
"sendEmail",
|
|
352
|
+
"sendWhatsappMessage",
|
|
353
|
+
"sendSms",
|
|
354
|
+
"sendWebchatMessage",
|
|
355
|
+
"sendTeamsMessage",
|
|
356
|
+
"sendInstagramMessage",
|
|
357
|
+
"sendMessengerMessage"
|
|
358
|
+
];
|
|
359
|
+
__name(isAllowedReviewableExecuteTool, "isAllowedReviewableExecuteTool");
|
|
360
|
+
__name2(isAllowedReviewableExecuteTool, "isAllowedReviewableExecuteTool");
|
|
361
|
+
REVIEWABLE_MCP_SEND_TOOL_SUFFIX = "_create_messaging_message";
|
|
362
|
+
__name(isReviewableMcpSendTool, "isReviewableMcpSendTool");
|
|
363
|
+
__name2(isReviewableMcpSendTool, "isReviewableMcpSendTool");
|
|
364
|
+
__name(isReviewableExecuteTool, "isReviewableExecuteTool");
|
|
365
|
+
__name2(isReviewableExecuteTool, "isReviewableExecuteTool");
|
|
366
|
+
NON_INTERACTIVE_CHANNELS = [
|
|
367
|
+
"trigger",
|
|
368
|
+
"agent-invocation"
|
|
369
|
+
];
|
|
370
|
+
__name(isInteractiveChannel, "isInteractiveChannel");
|
|
371
|
+
__name2(isInteractiveChannel, "isInteractiveChannel");
|
|
372
|
+
__name(isInteractiveTurn, "isInteractiveTurn");
|
|
373
|
+
__name2(isInteractiveTurn, "isInteractiveTurn");
|
|
558
374
|
__name(removeNavigateBlock, "removeNavigateBlock");
|
|
559
375
|
__name2(removeNavigateBlock, "removeNavigateBlock");
|
|
560
376
|
__name(transformChatHistoryContentParts, "transformChatHistoryContentParts");
|
|
561
377
|
__name2(transformChatHistoryContentParts, "transformChatHistoryContentParts");
|
|
378
|
+
RICH_PARTS_MESSAGE_ID_PREFIX = "rich-parts:";
|
|
379
|
+
SCREENSHOT_MESSAGE_ID_PREFIX = "screenshot:";
|
|
380
|
+
__name(isSyntheticSideRow, "isSyntheticSideRow");
|
|
381
|
+
__name2(isSyntheticSideRow, "isSyntheticSideRow");
|
|
382
|
+
__name(mergeRichPartMirrorMessages, "mergeRichPartMirrorMessages");
|
|
383
|
+
__name2(mergeRichPartMirrorMessages, "mergeRichPartMirrorMessages");
|
|
384
|
+
__name(citationDedupeKeys, "citationDedupeKeys");
|
|
385
|
+
__name2(citationDedupeKeys, "citationDedupeKeys");
|
|
386
|
+
__name(foldRichPartsIntoMessages, "foldRichPartsIntoMessages");
|
|
387
|
+
__name2(foldRichPartsIntoMessages, "foldRichPartsIntoMessages");
|
|
388
|
+
BROWSER_COMMANDS = [
|
|
389
|
+
// health + lifecycle / navigation
|
|
390
|
+
{
|
|
391
|
+
name: "health",
|
|
392
|
+
description: "Check the local browser engine is installed and responsive."
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
name: "session_open",
|
|
396
|
+
description: "Open/attach a browser session (its own cookies/auth). Args: url?, headed?, profile?, confirmActions?."
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
name: "navigate",
|
|
400
|
+
description: "Navigate the session to a URL. Args: url, waitUntil?."
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
name: "back",
|
|
404
|
+
description: "Go back in history."
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
name: "forward",
|
|
408
|
+
description: "Go forward in history."
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
name: "reload",
|
|
412
|
+
description: "Reload the current page."
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
name: "pushstate",
|
|
416
|
+
description: "SPA client-side navigation. Args: url."
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
name: "close",
|
|
420
|
+
description: "Close the session\u2019s browser."
|
|
421
|
+
},
|
|
422
|
+
// perception
|
|
423
|
+
{
|
|
424
|
+
name: "snapshot",
|
|
425
|
+
description: "Accessibility-tree snapshot with element refs (@e1\u2026) \u2014 see what to click/fill. Args: interactiveOnly?, selector?, urls?, compact?, depth?."
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
name: "get",
|
|
429
|
+
description: "Read from the page. Args: what(text|html|value|attr|title|url|count|box|styles), selector?, attr?."
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
name: "is",
|
|
433
|
+
description: "Check element state. Args: check(visible|enabled|checked), selector."
|
|
434
|
+
},
|
|
435
|
+
// interaction
|
|
436
|
+
{
|
|
437
|
+
name: "click",
|
|
438
|
+
description: "Click an element. Args: selector(@eN or CSS), newTab?."
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
name: "dblclick",
|
|
442
|
+
description: "Double-click an element. Args: selector."
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
name: "fill",
|
|
446
|
+
description: "Clear and fill a field. Args: selector, text."
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
name: "type",
|
|
450
|
+
description: "Type into an element. Args: selector, text."
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
name: "press",
|
|
454
|
+
description: "Press a key/chord (Enter, Control+a). Args: key."
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
name: "hover",
|
|
458
|
+
description: "Hover an element. Args: selector."
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
name: "focus",
|
|
462
|
+
description: "Focus an element. Args: selector."
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
name: "select",
|
|
466
|
+
description: "Select a dropdown option. Args: selector, value."
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
name: "check",
|
|
470
|
+
description: "Check a checkbox. Args: selector."
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
name: "uncheck",
|
|
474
|
+
description: "Uncheck a checkbox. Args: selector."
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
name: "scroll",
|
|
478
|
+
description: "Scroll. Args: direction(up|down|left|right), px?, selector?."
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
name: "scrollintoview",
|
|
482
|
+
description: "Scroll an element into view. Args: selector."
|
|
483
|
+
},
|
|
484
|
+
{
|
|
485
|
+
name: "drag",
|
|
486
|
+
description: "Drag and drop. Args: source, target."
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
name: "upload",
|
|
490
|
+
description: "Upload local file(s) to a file input. Args: selector, files[]."
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
name: "find",
|
|
494
|
+
description: "Act by semantic locator. Args: by(role|text|label|placeholder|alt|title|testid), query, action(click|fill|type|hover|focus|check|uncheck|text), value?, name?, exact?."
|
|
495
|
+
},
|
|
496
|
+
// AI fallbacks
|
|
497
|
+
{
|
|
498
|
+
name: "act",
|
|
499
|
+
description: "Act on the page: ref+action (deterministic) or natural-language instruction (engine AI). Args: ref?, action?, value?, instruction?."
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
name: "extract",
|
|
503
|
+
description: "Extract data by natural-language instruction (engine AI). Args: instruction."
|
|
504
|
+
},
|
|
505
|
+
// wait
|
|
506
|
+
{
|
|
507
|
+
name: "wait",
|
|
508
|
+
description: "Wait for a condition. Provide one of: selector(+state), ms, text, url, load, fn."
|
|
509
|
+
},
|
|
510
|
+
// tabs / frames
|
|
511
|
+
{
|
|
512
|
+
name: "tab",
|
|
513
|
+
description: "Manage tabs. Args: action(list|new|switch|close), target?, url?, label?."
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
name: "window_new",
|
|
517
|
+
description: "Open a new browser window. Args: url?."
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
name: "frame",
|
|
521
|
+
description: 'Switch frame context. Args: target(@eN | CSS | "main").'
|
|
522
|
+
},
|
|
523
|
+
// capture
|
|
524
|
+
{
|
|
525
|
+
name: "screenshot",
|
|
526
|
+
description: "Screenshot the page. Args: fullPage?, path?."
|
|
527
|
+
},
|
|
528
|
+
{
|
|
529
|
+
name: "pdf",
|
|
530
|
+
description: "Save the page as PDF. Args: path."
|
|
531
|
+
},
|
|
532
|
+
// state
|
|
533
|
+
{
|
|
534
|
+
name: "cookies",
|
|
535
|
+
description: "Manage cookies. Args: action(get|set|clear), name?, value?."
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
name: "storage",
|
|
539
|
+
description: "Manage web storage. Args: area(local|session), action(get|set|clear), key?, value?."
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
name: "set",
|
|
543
|
+
description: "Configure the browser. Args: setting(viewport|device|geo|headers|credentials|media), args[]."
|
|
544
|
+
},
|
|
545
|
+
// files / clipboard
|
|
546
|
+
{
|
|
547
|
+
name: "download",
|
|
548
|
+
description: "Download a file (click a selector to trigger, or wait for one). Args: selector?, path?."
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
name: "clipboard",
|
|
552
|
+
description: "Clipboard. Args: action(read|write|copy|paste), text?."
|
|
553
|
+
},
|
|
554
|
+
// auth (use-only)
|
|
555
|
+
{
|
|
556
|
+
name: "auth",
|
|
557
|
+
description: "Use a saved login profile. Args: action(login|list|show), name?. (Credentials are saved via the desktop, never the agent.)"
|
|
558
|
+
},
|
|
559
|
+
// confirmation gate
|
|
560
|
+
{
|
|
561
|
+
name: "confirm",
|
|
562
|
+
description: "Approve a pending confirmation_required action. Args: id."
|
|
563
|
+
},
|
|
564
|
+
{
|
|
565
|
+
name: "deny",
|
|
566
|
+
description: "Reject a pending confirmation_required action. Args: id."
|
|
567
|
+
},
|
|
568
|
+
// network / debug / input / state-files
|
|
569
|
+
{
|
|
570
|
+
name: "network",
|
|
571
|
+
description: "Inspect/control network. Args: action(route|unroute|requests|har) + relevant fields."
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
name: "console",
|
|
575
|
+
description: "View browser console messages. Args: clear?."
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
name: "errors",
|
|
579
|
+
description: "View uncaught page JS errors. Args: clear?."
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
name: "mouse",
|
|
583
|
+
description: "Low-level mouse. Args: action(move|down|up|wheel), x?, y?, button?, dy?, dx?."
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
name: "keyboard",
|
|
587
|
+
description: "Low-level keyboard at focus. Args: action(type|inserttext|keydown|keyup), text?, key?."
|
|
588
|
+
},
|
|
589
|
+
{
|
|
590
|
+
name: "state",
|
|
591
|
+
description: "Persist/restore storage+auth state to a file. Args: action(save|load|list|clear), path?."
|
|
592
|
+
}
|
|
593
|
+
];
|
|
594
|
+
BROWSER_COMMAND_NAMES = BROWSER_COMMANDS.map((c) => c.name);
|
|
595
|
+
REASONING_EFFORT_VALUES = [
|
|
596
|
+
"off",
|
|
597
|
+
"minimal",
|
|
598
|
+
"low",
|
|
599
|
+
"medium",
|
|
600
|
+
"high",
|
|
601
|
+
"max"
|
|
602
|
+
];
|
|
562
603
|
AGENT_NAME_TOKEN = "[Your Agent Name]";
|
|
563
604
|
DEFAULT_PERSONA_GUIDE = `# ${AGENT_NAME_TOKEN} - Persona
|
|
564
605
|
|
|
@@ -796,7 +837,15 @@ Feel free to add, remove, or rename sections. Your persona can be a single parag
|
|
|
796
837
|
// to the LLM as a ToolError — fills the 2–3s gap before the LLM's own
|
|
797
838
|
// recovery response. Persona-specific (keep it short and on-brand);
|
|
798
839
|
// absent → no spoken fallback (the LLM's recovery is the only signal).
|
|
799
|
-
onToolFailureSay: z.string().min(1).max(200).optional()
|
|
840
|
+
onToolFailureSay: z.string().min(1).max(200).optional(),
|
|
841
|
+
// Tool names to withhold from this voice agent's session. Matches ANY
|
|
842
|
+
// resolved tool: the platform base tools (searchKnowledgeBase, searchWeb,
|
|
843
|
+
// geocoding, the send* structured-output family), MCP/device tools, and the
|
|
844
|
+
// agent's own skill tools compiled into the artifact. Typical use is dropping
|
|
845
|
+
// the on-screen send* tools (`sendPayment`, `sendListItems`, …) on a
|
|
846
|
+
// screenless phone agent where they have nowhere to render. Names that match
|
|
847
|
+
// nothing are ignored (warn, not error) so a typo can't fail the push.
|
|
848
|
+
excludeTools: z.array(z.string().min(1)).optional()
|
|
800
849
|
});
|
|
801
850
|
LuaVoiceConfigSchema = LuaVoiceConfigInnerSchema.superRefine((cfg, ctx) => {
|
|
802
851
|
const isRealtime = cfg.llm.kind === "realtime";
|
|
@@ -839,11 +888,408 @@ Feel free to add, remove, or rename sections. Your persona can be a single parag
|
|
|
839
888
|
});
|
|
840
889
|
}
|
|
841
890
|
}
|
|
842
|
-
});
|
|
843
|
-
LuaVoiceRefSchema = z.object({
|
|
844
|
-
voiceId: z.string().min(1),
|
|
845
|
-
version: z.string().optional()
|
|
846
|
-
});
|
|
891
|
+
});
|
|
892
|
+
LuaVoiceRefSchema = z.object({
|
|
893
|
+
voiceId: z.string().min(1),
|
|
894
|
+
version: z.string().optional()
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
});
|
|
898
|
+
|
|
899
|
+
// src/interfaces/baskets.ts
|
|
900
|
+
var BasketStatus;
|
|
901
|
+
var init_baskets = __esm({
|
|
902
|
+
"src/interfaces/baskets.ts"() {
|
|
903
|
+
"use strict";
|
|
904
|
+
BasketStatus = /* @__PURE__ */ (function(BasketStatus2) {
|
|
905
|
+
BasketStatus2["ACTIVE"] = "active";
|
|
906
|
+
BasketStatus2["CHECKED_OUT"] = "checked_out";
|
|
907
|
+
BasketStatus2["ABANDONED"] = "abandoned";
|
|
908
|
+
BasketStatus2["EXPIRED"] = "expired";
|
|
909
|
+
return BasketStatus2;
|
|
910
|
+
})({});
|
|
911
|
+
}
|
|
912
|
+
});
|
|
913
|
+
|
|
914
|
+
// src/config/constants.ts
|
|
915
|
+
import { join } from "path";
|
|
916
|
+
import { homedir } from "os";
|
|
917
|
+
var CLI_CONFIG_DIR, VERSION_CHECK_FILE, TELEMETRY_FILE, CLI_CACHE_FILE, BASE_URLS, CREDENTIALS_FILE, SANDBOX_STORAGE_FILE, AUTH_STORAGE_FILE;
|
|
918
|
+
var init_constants = __esm({
|
|
919
|
+
"src/config/constants.ts"() {
|
|
920
|
+
"use strict";
|
|
921
|
+
CLI_CONFIG_DIR = join(homedir(), ".lua-cli");
|
|
922
|
+
VERSION_CHECK_FILE = join(CLI_CONFIG_DIR, "version-check.json");
|
|
923
|
+
TELEMETRY_FILE = join(CLI_CONFIG_DIR, "telemetry.json");
|
|
924
|
+
CLI_CACHE_FILE = join(CLI_CONFIG_DIR, "cache.json");
|
|
925
|
+
BASE_URLS = {
|
|
926
|
+
API: process.env.LUA_API_URL || "https://api.heylua.ai",
|
|
927
|
+
AUTH: process.env.LUA_AUTH_URL || "https://auth.heylua.ai",
|
|
928
|
+
CHAT: process.env.LUA_API_URL || "https://api.heylua.ai",
|
|
929
|
+
WEBHOOK: process.env.LUA_WEBHOOK_URL || "https://webhook.heylua.ai",
|
|
930
|
+
CDN: "https://cdn.heylua.ai"
|
|
931
|
+
};
|
|
932
|
+
CREDENTIALS_FILE = join(CLI_CONFIG_DIR, "credentials");
|
|
933
|
+
SANDBOX_STORAGE_FILE = join(CLI_CONFIG_DIR, "sandbox.json");
|
|
934
|
+
AUTH_STORAGE_FILE = join(CLI_CONFIG_DIR, "auth.json");
|
|
935
|
+
}
|
|
936
|
+
});
|
|
937
|
+
|
|
938
|
+
// src/errors/auth.error.ts
|
|
939
|
+
var AuthenticationError;
|
|
940
|
+
var init_auth_error = __esm({
|
|
941
|
+
"src/errors/auth.error.ts"() {
|
|
942
|
+
"use strict";
|
|
943
|
+
AuthenticationError = class _AuthenticationError extends Error {
|
|
944
|
+
static {
|
|
945
|
+
__name(this, "AuthenticationError");
|
|
946
|
+
}
|
|
947
|
+
statusCode = 401;
|
|
948
|
+
isAuthenticationError = true;
|
|
949
|
+
reason;
|
|
950
|
+
serverMessage;
|
|
951
|
+
/**
|
|
952
|
+
* If true, the error message already contains complete remediation steps
|
|
953
|
+
* and `withErrorHandling` should not append its own hint block. Use this
|
|
954
|
+
* when the throw site has more context about the right fix than the
|
|
955
|
+
* generic per-reason hints (e.g. `getToken()` listing all three ways to
|
|
956
|
+
* configure a key — keychain, env var, .env file).
|
|
957
|
+
*/
|
|
958
|
+
suppressDefaultRemediation;
|
|
959
|
+
constructor(message = "Invalid API key", reason = "unknown", serverMessage, suppressDefaultRemediation = false) {
|
|
960
|
+
super(message);
|
|
961
|
+
this.name = "AuthenticationError";
|
|
962
|
+
this.reason = reason;
|
|
963
|
+
this.serverMessage = serverMessage;
|
|
964
|
+
this.suppressDefaultRemediation = suppressDefaultRemediation;
|
|
965
|
+
if (Error.captureStackTrace) {
|
|
966
|
+
Error.captureStackTrace(this, _AuthenticationError);
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* Checks if an error is an AuthenticationError
|
|
971
|
+
* @param error - The error to check
|
|
972
|
+
* @returns True if the error is an AuthenticationError
|
|
973
|
+
*/
|
|
974
|
+
static isAuthenticationError(error) {
|
|
975
|
+
return error instanceof _AuthenticationError || error instanceof Error && "isAuthenticationError" in error && error.isAuthenticationError === true;
|
|
976
|
+
}
|
|
977
|
+
};
|
|
978
|
+
}
|
|
979
|
+
});
|
|
980
|
+
|
|
981
|
+
// src/api/http.client.ts
|
|
982
|
+
import { randomUUID } from "crypto";
|
|
983
|
+
var HttpClient;
|
|
984
|
+
var init_http_client = __esm({
|
|
985
|
+
"src/api/http.client.ts"() {
|
|
986
|
+
"use strict";
|
|
987
|
+
init_auth_error();
|
|
988
|
+
HttpClient = class {
|
|
989
|
+
static {
|
|
990
|
+
__name(this, "HttpClient");
|
|
991
|
+
}
|
|
992
|
+
baseUrl;
|
|
993
|
+
/**
|
|
994
|
+
* Creates an instance of HttpClient
|
|
995
|
+
* @param baseUrl - The base URL for all API requests
|
|
996
|
+
*/
|
|
997
|
+
constructor(baseUrl) {
|
|
998
|
+
this.baseUrl = baseUrl;
|
|
999
|
+
}
|
|
1000
|
+
/**
|
|
1001
|
+
* Makes an HTTP request with standardized error handling
|
|
1002
|
+
* @param url - The full URL to request
|
|
1003
|
+
* @param options - Fetch API request options
|
|
1004
|
+
* @returns Promise resolving to an ApiResponse with typed data
|
|
1005
|
+
* @private
|
|
1006
|
+
*/
|
|
1007
|
+
async request(url, options = {}) {
|
|
1008
|
+
const controller = new AbortController();
|
|
1009
|
+
const timeoutId = setTimeout(() => controller.abort(), 3e4);
|
|
1010
|
+
try {
|
|
1011
|
+
const response = await fetch(url, {
|
|
1012
|
+
...options,
|
|
1013
|
+
signal: controller.signal,
|
|
1014
|
+
headers: {
|
|
1015
|
+
"Content-Type": "application/json",
|
|
1016
|
+
...options.headers
|
|
1017
|
+
}
|
|
1018
|
+
});
|
|
1019
|
+
clearTimeout(timeoutId);
|
|
1020
|
+
if (!response.ok) {
|
|
1021
|
+
let errorData;
|
|
1022
|
+
try {
|
|
1023
|
+
errorData = await response.json();
|
|
1024
|
+
} catch (jsonError) {
|
|
1025
|
+
errorData = {};
|
|
1026
|
+
}
|
|
1027
|
+
if (response.status === 401) {
|
|
1028
|
+
const serverMessage = typeof errorData.message === "string" ? errorData.message : void 0;
|
|
1029
|
+
if (serverMessage && /not an admin/i.test(serverMessage)) {
|
|
1030
|
+
throw new AuthenticationError(`Access denied for this agent: ${serverMessage}`, "no_agent_access", serverMessage);
|
|
1031
|
+
}
|
|
1032
|
+
const isExplicitCredential = !!serverMessage && /(invalid|expired|missing|no)\s+(api[\s_-]?key|token|credential)/i.test(serverMessage);
|
|
1033
|
+
const isBareAuthRejection = !serverMessage || /^unauthorized$/i.test(serverMessage);
|
|
1034
|
+
if (isExplicitCredential || isBareAuthRejection) {
|
|
1035
|
+
throw new AuthenticationError("Authentication failed. Your API key may be invalid or expired.", "invalid_credentials", serverMessage);
|
|
1036
|
+
}
|
|
1037
|
+
throw new AuthenticationError(`Authentication failed: ${serverMessage}`, "unknown", serverMessage);
|
|
1038
|
+
}
|
|
1039
|
+
if (response.status === 403) {
|
|
1040
|
+
const detail = errorData.message || "You do not have permission to access this resource.";
|
|
1041
|
+
throw new Error(`Access denied (403): ${detail}
|
|
1042
|
+
Check that your API key has access to this agent/organization.`);
|
|
1043
|
+
}
|
|
1044
|
+
return {
|
|
1045
|
+
success: false,
|
|
1046
|
+
error: {
|
|
1047
|
+
message: errorData.message || `HTTP ${response.status}: ${response.statusText}`,
|
|
1048
|
+
statusCode: response.status,
|
|
1049
|
+
error: errorData.error,
|
|
1050
|
+
...errorData
|
|
1051
|
+
}
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
let data;
|
|
1055
|
+
try {
|
|
1056
|
+
data = await response.json();
|
|
1057
|
+
} catch (jsonError) {
|
|
1058
|
+
data = {};
|
|
1059
|
+
}
|
|
1060
|
+
if (typeof data === "object" && data !== null && "success" in data) {
|
|
1061
|
+
return data;
|
|
1062
|
+
}
|
|
1063
|
+
return {
|
|
1064
|
+
success: true,
|
|
1065
|
+
data
|
|
1066
|
+
};
|
|
1067
|
+
} catch (error) {
|
|
1068
|
+
clearTimeout(timeoutId);
|
|
1069
|
+
if (AuthenticationError.isAuthenticationError(error)) {
|
|
1070
|
+
throw error;
|
|
1071
|
+
}
|
|
1072
|
+
if (error instanceof Error && error.message.startsWith("Access denied (403)")) {
|
|
1073
|
+
throw error;
|
|
1074
|
+
}
|
|
1075
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
1076
|
+
return {
|
|
1077
|
+
success: false,
|
|
1078
|
+
error: {
|
|
1079
|
+
message: "Request timeout (30s)",
|
|
1080
|
+
statusCode: 0
|
|
1081
|
+
}
|
|
1082
|
+
};
|
|
1083
|
+
}
|
|
1084
|
+
return {
|
|
1085
|
+
success: false,
|
|
1086
|
+
error: {
|
|
1087
|
+
message: error instanceof Error ? error.message : "Network request failed",
|
|
1088
|
+
statusCode: 0
|
|
1089
|
+
}
|
|
1090
|
+
};
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
/**
|
|
1094
|
+
* Checks if an HTTP status code is retryable
|
|
1095
|
+
* @param statusCode - The HTTP status code (0 for network errors)
|
|
1096
|
+
* @returns True if the request should be retried
|
|
1097
|
+
* @private
|
|
1098
|
+
*/
|
|
1099
|
+
isRetryableStatus(statusCode) {
|
|
1100
|
+
return statusCode === 0 || statusCode === 429 || statusCode >= 500 && statusCode <= 504;
|
|
1101
|
+
}
|
|
1102
|
+
/**
|
|
1103
|
+
* Calculates exponential backoff with full jitter (AWS best practice)
|
|
1104
|
+
* @param attempt - The retry attempt number (0-based)
|
|
1105
|
+
* @param baseMs - Base delay in milliseconds
|
|
1106
|
+
* @param maxMs - Maximum delay cap in milliseconds
|
|
1107
|
+
* @returns Delay in milliseconds with random jitter
|
|
1108
|
+
* @private
|
|
1109
|
+
*/
|
|
1110
|
+
calculateBackoff(attempt, baseMs = 1e3, maxMs = 15e3) {
|
|
1111
|
+
const exponential = Math.min(maxMs, baseMs * Math.pow(2, attempt));
|
|
1112
|
+
return Math.max(100, Math.random() * exponential);
|
|
1113
|
+
}
|
|
1114
|
+
/**
|
|
1115
|
+
* Wraps request with retry logic for transient failures
|
|
1116
|
+
* @param url - The full URL to request
|
|
1117
|
+
* @param options - Fetch API request options
|
|
1118
|
+
* @param maxRetries - Maximum number of retry attempts (default 3)
|
|
1119
|
+
* @returns Promise resolving to an ApiResponse with typed data
|
|
1120
|
+
* @private
|
|
1121
|
+
*/
|
|
1122
|
+
async retryableRequest(url, options = {}, maxRetries = 3) {
|
|
1123
|
+
if (options.method === "POST") {
|
|
1124
|
+
const headers = options.headers || {};
|
|
1125
|
+
if (!headers["X-Idempotency-Key"]) {
|
|
1126
|
+
headers["X-Idempotency-Key"] = randomUUID();
|
|
1127
|
+
options = {
|
|
1128
|
+
...options,
|
|
1129
|
+
headers: {
|
|
1130
|
+
...options.headers,
|
|
1131
|
+
...headers
|
|
1132
|
+
}
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
let lastResult = null;
|
|
1137
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
1138
|
+
try {
|
|
1139
|
+
const result = await this.request(url, options);
|
|
1140
|
+
if (result.success || !result.error || !this.isRetryableStatus(result.error.statusCode || 0)) {
|
|
1141
|
+
return result;
|
|
1142
|
+
}
|
|
1143
|
+
lastResult = result;
|
|
1144
|
+
} catch (error) {
|
|
1145
|
+
throw error;
|
|
1146
|
+
}
|
|
1147
|
+
if (attempt < maxRetries) {
|
|
1148
|
+
const backoff = this.calculateBackoff(attempt);
|
|
1149
|
+
await new Promise((resolve) => setTimeout(resolve, backoff));
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
return lastResult;
|
|
1153
|
+
}
|
|
1154
|
+
/**
|
|
1155
|
+
* Performs an HTTP GET request
|
|
1156
|
+
* @param url - The relative URL path to request (will be appended to baseUrl)
|
|
1157
|
+
* @param headers - Optional HTTP headers to include in the request
|
|
1158
|
+
* @returns Promise resolving to an ApiResponse with typed data
|
|
1159
|
+
* @protected
|
|
1160
|
+
*/
|
|
1161
|
+
async httpGet(url, headers) {
|
|
1162
|
+
return this.retryableRequest(this.baseUrl + url, {
|
|
1163
|
+
method: "GET",
|
|
1164
|
+
headers
|
|
1165
|
+
});
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* Performs an HTTP POST request
|
|
1169
|
+
* @param url - The relative URL path to request (will be appended to baseUrl)
|
|
1170
|
+
* @param data - Optional request body data (will be JSON stringified)
|
|
1171
|
+
* @param headers - Optional HTTP headers to include in the request
|
|
1172
|
+
* @returns Promise resolving to an ApiResponse with typed data
|
|
1173
|
+
* @protected
|
|
1174
|
+
*/
|
|
1175
|
+
async httpPost(url, data, headers) {
|
|
1176
|
+
return this.retryableRequest(this.baseUrl + url, {
|
|
1177
|
+
method: "POST",
|
|
1178
|
+
body: data ? JSON.stringify(data) : void 0,
|
|
1179
|
+
headers
|
|
1180
|
+
});
|
|
1181
|
+
}
|
|
1182
|
+
/**
|
|
1183
|
+
* Performs an HTTP PUT request
|
|
1184
|
+
* @param url - The relative URL path to request (will be appended to baseUrl)
|
|
1185
|
+
* @param data - Optional request body data (will be JSON stringified)
|
|
1186
|
+
* @param headers - Optional HTTP headers to include in the request
|
|
1187
|
+
* @returns Promise resolving to an ApiResponse with typed data
|
|
1188
|
+
* @protected
|
|
1189
|
+
*/
|
|
1190
|
+
async httpPut(url, data, headers) {
|
|
1191
|
+
return this.retryableRequest(this.baseUrl + url, {
|
|
1192
|
+
method: "PUT",
|
|
1193
|
+
body: data ? JSON.stringify(data) : void 0,
|
|
1194
|
+
headers
|
|
1195
|
+
});
|
|
1196
|
+
}
|
|
1197
|
+
/**
|
|
1198
|
+
* Performs an HTTP DELETE request
|
|
1199
|
+
* @param url - The relative URL path to request (will be appended to baseUrl)
|
|
1200
|
+
* @param headers - Optional HTTP headers to include in the request
|
|
1201
|
+
* @returns Promise resolving to an ApiResponse with typed data
|
|
1202
|
+
* @protected
|
|
1203
|
+
*/
|
|
1204
|
+
async httpDelete(url, headers) {
|
|
1205
|
+
return this.retryableRequest(this.baseUrl + url, {
|
|
1206
|
+
method: "DELETE",
|
|
1207
|
+
headers
|
|
1208
|
+
});
|
|
1209
|
+
}
|
|
1210
|
+
/**
|
|
1211
|
+
* Performs an HTTP PATCH request
|
|
1212
|
+
* @param url - The relative URL path to request (will be appended to baseUrl)
|
|
1213
|
+
* @param data - Optional request body data (will be JSON stringified)
|
|
1214
|
+
* @param headers - Optional HTTP headers to include in the request
|
|
1215
|
+
* @returns Promise resolving to an ApiResponse with typed data
|
|
1216
|
+
* @protected
|
|
1217
|
+
*/
|
|
1218
|
+
async httpPatch(url, data, headers) {
|
|
1219
|
+
return this.retryableRequest(this.baseUrl + url, {
|
|
1220
|
+
method: "PATCH",
|
|
1221
|
+
body: data ? JSON.stringify(data) : void 0,
|
|
1222
|
+
headers
|
|
1223
|
+
});
|
|
1224
|
+
}
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
});
|
|
1228
|
+
|
|
1229
|
+
// src/api/auth.api.service.ts
|
|
1230
|
+
var init_auth_api_service = __esm({
|
|
1231
|
+
"src/api/auth.api.service.ts"() {
|
|
1232
|
+
"use strict";
|
|
1233
|
+
init_http_client();
|
|
1234
|
+
}
|
|
1235
|
+
});
|
|
1236
|
+
|
|
1237
|
+
// src/services/auth.ts
|
|
1238
|
+
import "dotenv/config";
|
|
1239
|
+
import { readFileSync, writeFileSync, mkdirSync, unlinkSync } from "fs";
|
|
1240
|
+
function getToken() {
|
|
1241
|
+
if (process.env.LUA_API_KEY) {
|
|
1242
|
+
return process.env.LUA_API_KEY;
|
|
1243
|
+
}
|
|
1244
|
+
try {
|
|
1245
|
+
const token = readFileSync(CREDENTIALS_FILE, "utf8").trim();
|
|
1246
|
+
if (token) return token;
|
|
1247
|
+
} catch {
|
|
1248
|
+
}
|
|
1249
|
+
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);
|
|
1250
|
+
}
|
|
1251
|
+
var init_auth = __esm({
|
|
1252
|
+
"src/services/auth.ts"() {
|
|
1253
|
+
"use strict";
|
|
1254
|
+
init_auth_api_service();
|
|
1255
|
+
init_constants();
|
|
1256
|
+
init_auth_error();
|
|
1257
|
+
__name(getToken, "getToken");
|
|
1258
|
+
}
|
|
1259
|
+
});
|
|
1260
|
+
|
|
1261
|
+
// src/config/compile.constants.ts
|
|
1262
|
+
var COMPILE_DIRS, COMPILE_FILES, SKILL_DEFAULTS, YAML_FORMAT;
|
|
1263
|
+
var init_compile_constants = __esm({
|
|
1264
|
+
"src/config/compile.constants.ts"() {
|
|
1265
|
+
"use strict";
|
|
1266
|
+
COMPILE_DIRS = {
|
|
1267
|
+
DIST: "dist",
|
|
1268
|
+
DIST_V2: "dist-v2",
|
|
1269
|
+
LUA: ".lua",
|
|
1270
|
+
TOOLS: "tools"
|
|
1271
|
+
};
|
|
1272
|
+
COMPILE_FILES = {
|
|
1273
|
+
DEPLOYMENT_JSON: "deployment.json",
|
|
1274
|
+
DEPLOY_JSON: "deploy.json",
|
|
1275
|
+
MANIFEST_JSON: "manifest.json",
|
|
1276
|
+
INDEX_TS: "index.ts",
|
|
1277
|
+
INDEX_JS: "index.js",
|
|
1278
|
+
PACKAGE_JSON: "package.json",
|
|
1279
|
+
TSCONFIG_JSON: "tsconfig.json",
|
|
1280
|
+
LUA_SKILL_YAML: "lua.skill.yaml"
|
|
1281
|
+
};
|
|
1282
|
+
SKILL_DEFAULTS = {
|
|
1283
|
+
NAME: "lua-skill",
|
|
1284
|
+
VERSION: "1.0.0",
|
|
1285
|
+
DESCRIPTION: "",
|
|
1286
|
+
CONTEXT: ""
|
|
1287
|
+
};
|
|
1288
|
+
YAML_FORMAT = {
|
|
1289
|
+
INDENT: 2,
|
|
1290
|
+
LINE_WIDTH: -1,
|
|
1291
|
+
NO_REFS: true
|
|
1292
|
+
};
|
|
847
1293
|
}
|
|
848
1294
|
});
|
|
849
1295
|
|
|
@@ -857,6 +1303,7 @@ var init_types = __esm({
|
|
|
857
1303
|
PrimitiveKind2["SKILL"] = "skill";
|
|
858
1304
|
PrimitiveKind2["JOB"] = "job";
|
|
859
1305
|
PrimitiveKind2["WEBHOOK"] = "webhook";
|
|
1306
|
+
PrimitiveKind2["TRIGGER"] = "trigger";
|
|
860
1307
|
PrimitiveKind2["PREPROCESSOR"] = "preprocessor";
|
|
861
1308
|
PrimitiveKind2["POSTPROCESSOR"] = "postprocessor";
|
|
862
1309
|
PrimitiveKind2["MCP_SERVER"] = "mcp-server";
|
|
@@ -1730,7 +2177,8 @@ var init_skill_handler = __esm({
|
|
|
1730
2177
|
const response = await api.publishSkillVersion(entityId, version);
|
|
1731
2178
|
return {
|
|
1732
2179
|
success: response.success,
|
|
1733
|
-
error: response.error?.message
|
|
2180
|
+
error: response.error?.message,
|
|
2181
|
+
agentVersion: response.data?.agentVersion
|
|
1734
2182
|
};
|
|
1735
2183
|
}
|
|
1736
2184
|
prepareForPush(manifest, name, projectPath = process.cwd(), bundleAccumulator) {
|
|
@@ -4607,6 +5055,12 @@ var init_agents_api_service = __esm({
|
|
|
4607
5055
|
} : {},
|
|
4608
5056
|
...body.threadId !== void 0 ? {
|
|
4609
5057
|
threadId: body.threadId
|
|
5058
|
+
} : {},
|
|
5059
|
+
...body.webhookPayload !== void 0 ? {
|
|
5060
|
+
webhookPayload: body.webhookPayload
|
|
5061
|
+
} : {},
|
|
5062
|
+
...body.clientContext !== void 0 ? {
|
|
5063
|
+
clientContext: body.clientContext
|
|
4610
5064
|
} : {}
|
|
4611
5065
|
};
|
|
4612
5066
|
}
|
|
@@ -4989,6 +5443,30 @@ var init_voice_api_service = __esm({
|
|
|
4989
5443
|
});
|
|
4990
5444
|
}
|
|
4991
5445
|
/**
|
|
5446
|
+
* Create a voice room + client access token for a custom frontend
|
|
5447
|
+
* (standard livekit-client). The session runs under a synthetic identity;
|
|
5448
|
+
* pass `userId` to scope conversation memory + transcript to your own end
|
|
5449
|
+
* user. Wraps `POST /developer/voice/:agentId/session`.
|
|
5450
|
+
*/
|
|
5451
|
+
async createSession(input = {}) {
|
|
5452
|
+
return this.httpPost(`/developer/voice/${this.agentId}/session`, input, {
|
|
5453
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
5454
|
+
});
|
|
5455
|
+
}
|
|
5456
|
+
/**
|
|
5457
|
+
* Sandbox helper: throws on non-success and returns the unwrapped output.
|
|
5458
|
+
*/
|
|
5459
|
+
async createSessionForSandbox(input = {}) {
|
|
5460
|
+
const result = await this.createSession(input);
|
|
5461
|
+
if (!result.success) {
|
|
5462
|
+
throw new Error(result.error?.message || "Voice session creation failed");
|
|
5463
|
+
}
|
|
5464
|
+
if (!result.data) {
|
|
5465
|
+
throw new Error("Voice session creation failed: empty response");
|
|
5466
|
+
}
|
|
5467
|
+
return result.data;
|
|
5468
|
+
}
|
|
5469
|
+
/**
|
|
4992
5470
|
* Sandbox helper: throws on non-success and returns the unwrapped output.
|
|
4993
5471
|
* Mirrors the shape `AgentsApiService.invokeForSandbox` exposes so the
|
|
4994
5472
|
* `Voice` namespace in `api-exports.ts` stays a one-liner.
|
|
@@ -5007,6 +5485,134 @@ var init_voice_api_service = __esm({
|
|
|
5007
5485
|
}
|
|
5008
5486
|
});
|
|
5009
5487
|
|
|
5488
|
+
// src/api/channels-send.api.service.ts
|
|
5489
|
+
var ChannelsSendApiService;
|
|
5490
|
+
var init_channels_send_api_service = __esm({
|
|
5491
|
+
"src/api/channels-send.api.service.ts"() {
|
|
5492
|
+
"use strict";
|
|
5493
|
+
init_http_client();
|
|
5494
|
+
ChannelsSendApiService = class extends HttpClient {
|
|
5495
|
+
static {
|
|
5496
|
+
__name(this, "ChannelsSendApiService");
|
|
5497
|
+
}
|
|
5498
|
+
apiKey;
|
|
5499
|
+
agentId;
|
|
5500
|
+
constructor(baseUrl, apiKey, agentId) {
|
|
5501
|
+
super(baseUrl), this.apiKey = apiKey, this.agentId = agentId;
|
|
5502
|
+
}
|
|
5503
|
+
/** POST /developer/agents/:agentId/channels/send */
|
|
5504
|
+
async send(input) {
|
|
5505
|
+
return this.httpPost(`/developer/agents/${this.agentId}/channels/send`, input, {
|
|
5506
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
5507
|
+
});
|
|
5508
|
+
}
|
|
5509
|
+
/** POST /developer/agents/:agentId/channels/whatsapp/template */
|
|
5510
|
+
async sendWhatsAppTemplate(input) {
|
|
5511
|
+
return this.httpPost(`/developer/agents/${this.agentId}/channels/whatsapp/template`, input, {
|
|
5512
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
5513
|
+
});
|
|
5514
|
+
}
|
|
5515
|
+
/** POST /developer/agents/:agentId/channels/whatsapp/reaction */
|
|
5516
|
+
async sendWhatsAppReaction(input) {
|
|
5517
|
+
return this.httpPost(`/developer/agents/${this.agentId}/channels/whatsapp/reaction`, input, {
|
|
5518
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
5519
|
+
});
|
|
5520
|
+
}
|
|
5521
|
+
/** POST /developer/agents/:agentId/channels/email/send */
|
|
5522
|
+
async sendEmail(input) {
|
|
5523
|
+
return this.httpPost(`/developer/agents/${this.agentId}/channels/email/send`, input, {
|
|
5524
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
5525
|
+
});
|
|
5526
|
+
}
|
|
5527
|
+
/**
|
|
5528
|
+
* Sandbox helper: throws on non-success, returns unwrapped output.
|
|
5529
|
+
* A 200 with `persisted: false` is NOT an error — it passes through.
|
|
5530
|
+
*/
|
|
5531
|
+
async sendForSandbox(input) {
|
|
5532
|
+
const result = await this.send(input);
|
|
5533
|
+
if (!result.success) {
|
|
5534
|
+
throw new Error(result.error?.message || "Channel send failed");
|
|
5535
|
+
}
|
|
5536
|
+
if (!result.data) {
|
|
5537
|
+
throw new Error("Channel send failed: empty response");
|
|
5538
|
+
}
|
|
5539
|
+
return result.data;
|
|
5540
|
+
}
|
|
5541
|
+
/** Sandbox helper for WhatsApp template sends. */
|
|
5542
|
+
async sendWhatsAppTemplateForSandbox(input) {
|
|
5543
|
+
const result = await this.sendWhatsAppTemplate(input);
|
|
5544
|
+
if (!result.success) {
|
|
5545
|
+
throw new Error(result.error?.message || "WhatsApp template send failed");
|
|
5546
|
+
}
|
|
5547
|
+
if (!result.data) {
|
|
5548
|
+
throw new Error("WhatsApp template send failed: empty response");
|
|
5549
|
+
}
|
|
5550
|
+
return result.data;
|
|
5551
|
+
}
|
|
5552
|
+
/** Sandbox helper for WhatsApp reaction sends. */
|
|
5553
|
+
async sendWhatsAppReactionForSandbox(input) {
|
|
5554
|
+
const result = await this.sendWhatsAppReaction(input);
|
|
5555
|
+
if (!result.success) {
|
|
5556
|
+
throw new Error(result.error?.message || "WhatsApp reaction send failed");
|
|
5557
|
+
}
|
|
5558
|
+
if (!result.data) {
|
|
5559
|
+
throw new Error("WhatsApp reaction send failed: empty response");
|
|
5560
|
+
}
|
|
5561
|
+
return result.data;
|
|
5562
|
+
}
|
|
5563
|
+
/** Sandbox helper for email sends. */
|
|
5564
|
+
async sendEmailForSandbox(input) {
|
|
5565
|
+
const result = await this.sendEmail(input);
|
|
5566
|
+
if (!result.success) {
|
|
5567
|
+
throw new Error(result.error?.message || "Email send failed");
|
|
5568
|
+
}
|
|
5569
|
+
if (!result.data) {
|
|
5570
|
+
throw new Error("Email send failed: empty response");
|
|
5571
|
+
}
|
|
5572
|
+
return result.data;
|
|
5573
|
+
}
|
|
5574
|
+
};
|
|
5575
|
+
}
|
|
5576
|
+
});
|
|
5577
|
+
|
|
5578
|
+
// src/api/directory.api.service.ts
|
|
5579
|
+
var DirectoryApiService;
|
|
5580
|
+
var init_directory_api_service = __esm({
|
|
5581
|
+
"src/api/directory.api.service.ts"() {
|
|
5582
|
+
"use strict";
|
|
5583
|
+
init_http_client();
|
|
5584
|
+
DirectoryApiService = class extends HttpClient {
|
|
5585
|
+
static {
|
|
5586
|
+
__name(this, "DirectoryApiService");
|
|
5587
|
+
}
|
|
5588
|
+
apiKey;
|
|
5589
|
+
agentId;
|
|
5590
|
+
constructor(baseUrl, apiKey, agentId) {
|
|
5591
|
+
super(baseUrl), this.apiKey = apiKey, this.agentId = agentId;
|
|
5592
|
+
}
|
|
5593
|
+
/** POST /developer/agents/:agentId/directory/resolve */
|
|
5594
|
+
async resolve(name) {
|
|
5595
|
+
return this.httpPost(`/developer/agents/${this.agentId}/directory/resolve`, {
|
|
5596
|
+
name
|
|
5597
|
+
}, {
|
|
5598
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
5599
|
+
});
|
|
5600
|
+
}
|
|
5601
|
+
/** Sandbox helper: throws on non-success, returns unwrapped result. */
|
|
5602
|
+
async resolveForSandbox(name) {
|
|
5603
|
+
const result = await this.resolve(name);
|
|
5604
|
+
if (!result.success) {
|
|
5605
|
+
throw new Error(result.error?.message || "Directory resolve failed");
|
|
5606
|
+
}
|
|
5607
|
+
if (!result.data) {
|
|
5608
|
+
throw new Error("Directory resolve failed: empty response");
|
|
5609
|
+
}
|
|
5610
|
+
return result.data;
|
|
5611
|
+
}
|
|
5612
|
+
};
|
|
5613
|
+
}
|
|
5614
|
+
});
|
|
5615
|
+
|
|
5010
5616
|
// src/api/device.api.service.ts
|
|
5011
5617
|
var device_api_service_exports = {};
|
|
5012
5618
|
__export(device_api_service_exports, {
|
|
@@ -5099,9 +5705,11 @@ __export(lazy_instances_exports, {
|
|
|
5099
5705
|
getAiInstance: () => getAiInstance,
|
|
5100
5706
|
getBasketsInstance: () => getBasketsInstance,
|
|
5101
5707
|
getCdnInstance: () => getCdnInstance,
|
|
5708
|
+
getChannelsSendInstance: () => getChannelsSendInstance,
|
|
5102
5709
|
getDataInstance: () => getDataInstance,
|
|
5103
5710
|
getDeveloperInstance: () => getDeveloperInstance,
|
|
5104
5711
|
getDeviceInstance: () => getDeviceInstance,
|
|
5712
|
+
getDirectoryInstance: () => getDirectoryInstance,
|
|
5105
5713
|
getJobInstance: () => getJobInstance,
|
|
5106
5714
|
getOrderInstance: () => getOrderInstance,
|
|
5107
5715
|
getProductsInstance: () => getProductsInstance,
|
|
@@ -5209,6 +5817,20 @@ async function getVoiceInstance() {
|
|
|
5209
5817
|
}
|
|
5210
5818
|
return _voiceInstance;
|
|
5211
5819
|
}
|
|
5820
|
+
async function getChannelsSendInstance() {
|
|
5821
|
+
if (!_channelsSendInstance) {
|
|
5822
|
+
const creds = await getCredentials();
|
|
5823
|
+
_channelsSendInstance = new ChannelsSendApiService(BASE_URLS.API, creds.apiKey, creds.agentId);
|
|
5824
|
+
}
|
|
5825
|
+
return _channelsSendInstance;
|
|
5826
|
+
}
|
|
5827
|
+
async function getDirectoryInstance() {
|
|
5828
|
+
if (!_directoryInstance) {
|
|
5829
|
+
const creds = await getCredentials();
|
|
5830
|
+
_directoryInstance = new DirectoryApiService(BASE_URLS.API, creds.apiKey, creds.agentId);
|
|
5831
|
+
}
|
|
5832
|
+
return _directoryInstance;
|
|
5833
|
+
}
|
|
5212
5834
|
function clearAllInstances() {
|
|
5213
5835
|
_userInstance = null;
|
|
5214
5836
|
_dataInstance = null;
|
|
@@ -5223,8 +5845,10 @@ function clearAllInstances() {
|
|
|
5223
5845
|
_cdnInstance = null;
|
|
5224
5846
|
_developerInstance = null;
|
|
5225
5847
|
_voiceInstance = null;
|
|
5848
|
+
_channelsSendInstance = null;
|
|
5849
|
+
_directoryInstance = null;
|
|
5226
5850
|
}
|
|
5227
|
-
var _userInstance, _dataInstance, _productsInstance, _basketsInstance, _orderInstance, _webhookInstance, _jobInstance, _aiInstance, _agentsInstance, _whatsAppTemplatesInstance, _cdnInstance, _developerInstance, _voiceInstance, _deviceInstance;
|
|
5851
|
+
var _userInstance, _dataInstance, _productsInstance, _basketsInstance, _orderInstance, _webhookInstance, _jobInstance, _aiInstance, _agentsInstance, _whatsAppTemplatesInstance, _cdnInstance, _developerInstance, _voiceInstance, _channelsSendInstance, _directoryInstance, _deviceInstance;
|
|
5228
5852
|
var init_lazy_instances = __esm({
|
|
5229
5853
|
"src/api/lazy-instances.ts"() {
|
|
5230
5854
|
"use strict";
|
|
@@ -5243,6 +5867,8 @@ var init_lazy_instances = __esm({
|
|
|
5243
5867
|
init_cdn_api_service();
|
|
5244
5868
|
init_developer_api_service();
|
|
5245
5869
|
init_voice_api_service();
|
|
5870
|
+
init_channels_send_api_service();
|
|
5871
|
+
init_directory_api_service();
|
|
5246
5872
|
_userInstance = null;
|
|
5247
5873
|
_dataInstance = null;
|
|
5248
5874
|
_productsInstance = null;
|
|
@@ -5256,6 +5882,8 @@ var init_lazy_instances = __esm({
|
|
|
5256
5882
|
_cdnInstance = null;
|
|
5257
5883
|
_developerInstance = null;
|
|
5258
5884
|
_voiceInstance = null;
|
|
5885
|
+
_channelsSendInstance = null;
|
|
5886
|
+
_directoryInstance = null;
|
|
5259
5887
|
__name(getUserInstance, "getUserInstance");
|
|
5260
5888
|
__name(getDataInstance, "getDataInstance");
|
|
5261
5889
|
__name(getProductsInstance, "getProductsInstance");
|
|
@@ -5271,6 +5899,8 @@ var init_lazy_instances = __esm({
|
|
|
5271
5899
|
__name(getDeviceInstance, "getDeviceInstance");
|
|
5272
5900
|
__name(getDeveloperInstance, "getDeveloperInstance");
|
|
5273
5901
|
__name(getVoiceInstance, "getVoiceInstance");
|
|
5902
|
+
__name(getChannelsSendInstance, "getChannelsSendInstance");
|
|
5903
|
+
__name(getDirectoryInstance, "getDirectoryInstance");
|
|
5274
5904
|
__name(clearAllInstances, "clearAllInstances");
|
|
5275
5905
|
}
|
|
5276
5906
|
});
|
|
@@ -5289,6 +5919,7 @@ function assertValidToolName(name) {
|
|
|
5289
5919
|
__name(assertValidToolName, "assertValidToolName");
|
|
5290
5920
|
|
|
5291
5921
|
// src/types/skill.ts
|
|
5922
|
+
init_dist();
|
|
5292
5923
|
var env = /* @__PURE__ */ __name((key) => {
|
|
5293
5924
|
if (process.env[key]) {
|
|
5294
5925
|
return process.env[key];
|
|
@@ -5557,6 +6188,39 @@ var LuaWebhook = class {
|
|
|
5557
6188
|
return this.executeFunction(event);
|
|
5558
6189
|
}
|
|
5559
6190
|
};
|
|
6191
|
+
var LuaTrigger = class {
|
|
6192
|
+
static {
|
|
6193
|
+
__name(this, "LuaTrigger");
|
|
6194
|
+
}
|
|
6195
|
+
name;
|
|
6196
|
+
description;
|
|
6197
|
+
source;
|
|
6198
|
+
inputSchema;
|
|
6199
|
+
verify;
|
|
6200
|
+
filter;
|
|
6201
|
+
transform;
|
|
6202
|
+
constructor(config) {
|
|
6203
|
+
if (!config.name || !config.name.trim()) {
|
|
6204
|
+
throw new Error("LuaTrigger requires a non-empty `name` (used as the server-side identifier).");
|
|
6205
|
+
}
|
|
6206
|
+
if (!config.verify && !config.filter && !config.transform) {
|
|
6207
|
+
throw new Error("LuaTrigger requires at least one of verify, filter, or transform.");
|
|
6208
|
+
}
|
|
6209
|
+
this.name = config.name;
|
|
6210
|
+
this.description = config.description;
|
|
6211
|
+
this.source = config.source ?? "webhook";
|
|
6212
|
+
this.inputSchema = config.inputSchema;
|
|
6213
|
+
this.verify = config.verify;
|
|
6214
|
+
this.filter = config.filter;
|
|
6215
|
+
this.transform = config.transform;
|
|
6216
|
+
}
|
|
6217
|
+
getName() {
|
|
6218
|
+
return this.name;
|
|
6219
|
+
}
|
|
6220
|
+
getDescription() {
|
|
6221
|
+
return this.description;
|
|
6222
|
+
}
|
|
6223
|
+
};
|
|
5560
6224
|
var PreProcessor = class {
|
|
5561
6225
|
static {
|
|
5562
6226
|
__name(this, "PreProcessor");
|
|
@@ -5700,6 +6364,18 @@ function validateModelSettings(settings) {
|
|
|
5700
6364
|
throw new Error("Agent modelSettings.stopSequences must be a string array");
|
|
5701
6365
|
}
|
|
5702
6366
|
}
|
|
6367
|
+
if (settings.reasoning !== void 0) {
|
|
6368
|
+
if (typeof settings.reasoning !== "object" || settings.reasoning === null || Array.isArray(settings.reasoning)) {
|
|
6369
|
+
throw new Error("Agent modelSettings.reasoning must be an object");
|
|
6370
|
+
}
|
|
6371
|
+
const { effort, show } = settings.reasoning;
|
|
6372
|
+
if (effort !== void 0 && !REASONING_EFFORT_VALUES.includes(effort)) {
|
|
6373
|
+
throw new Error(`Agent modelSettings.reasoning.effort must be one of: ${REASONING_EFFORT_VALUES.join(", ")}`);
|
|
6374
|
+
}
|
|
6375
|
+
if (show !== void 0 && typeof show !== "boolean") {
|
|
6376
|
+
throw new Error("Agent modelSettings.reasoning.show must be a boolean");
|
|
6377
|
+
}
|
|
6378
|
+
}
|
|
5703
6379
|
}
|
|
5704
6380
|
__name(validateModelSettings, "validateModelSettings");
|
|
5705
6381
|
var LuaAgent = class {
|
|
@@ -5712,6 +6388,7 @@ var LuaAgent = class {
|
|
|
5712
6388
|
modelSettings;
|
|
5713
6389
|
skills;
|
|
5714
6390
|
webhooks;
|
|
6391
|
+
triggers;
|
|
5715
6392
|
jobs;
|
|
5716
6393
|
preProcessors;
|
|
5717
6394
|
postProcessors;
|
|
@@ -5721,6 +6398,7 @@ var LuaAgent = class {
|
|
|
5721
6398
|
voices;
|
|
5722
6399
|
batching;
|
|
5723
6400
|
governance;
|
|
6401
|
+
browser;
|
|
5724
6402
|
/**
|
|
5725
6403
|
* Creates a new LuaAgent instance.
|
|
5726
6404
|
*
|
|
@@ -5752,6 +6430,7 @@ var LuaAgent = class {
|
|
|
5752
6430
|
}
|
|
5753
6431
|
this.skills = config.skills || [];
|
|
5754
6432
|
this.webhooks = config.webhooks || [];
|
|
6433
|
+
this.triggers = config.triggers || [];
|
|
5755
6434
|
this.jobs = config.jobs || [];
|
|
5756
6435
|
this.preProcessors = config.preProcessors || [];
|
|
5757
6436
|
this.postProcessors = config.postProcessors || [];
|
|
@@ -5761,10 +6440,15 @@ var LuaAgent = class {
|
|
|
5761
6440
|
this.voices = config.voices;
|
|
5762
6441
|
this.batching = config.batching;
|
|
5763
6442
|
this.governance = config.governance;
|
|
6443
|
+
this.browser = config.browser;
|
|
5764
6444
|
}
|
|
5765
6445
|
getName() {
|
|
5766
6446
|
return this.name;
|
|
5767
6447
|
}
|
|
6448
|
+
/** Browser switch (LuaBrowser) — `true`/config when the agent can browse. */
|
|
6449
|
+
getBrowser() {
|
|
6450
|
+
return this.browser;
|
|
6451
|
+
}
|
|
5768
6452
|
getPersona() {
|
|
5769
6453
|
return this.persona;
|
|
5770
6454
|
}
|
|
@@ -5780,6 +6464,9 @@ var LuaAgent = class {
|
|
|
5780
6464
|
getWebhooks() {
|
|
5781
6465
|
return this.webhooks;
|
|
5782
6466
|
}
|
|
6467
|
+
getTriggers() {
|
|
6468
|
+
return this.triggers;
|
|
6469
|
+
}
|
|
5783
6470
|
getJobs() {
|
|
5784
6471
|
return this.jobs;
|
|
5785
6472
|
}
|
|
@@ -5879,6 +6566,7 @@ var LuaVoice = class {
|
|
|
5879
6566
|
preemptiveGeneration;
|
|
5880
6567
|
interruption;
|
|
5881
6568
|
sttLanguage;
|
|
6569
|
+
excludeTools;
|
|
5882
6570
|
tools;
|
|
5883
6571
|
onEnter;
|
|
5884
6572
|
onUserTurnCompleted;
|
|
@@ -5901,6 +6589,7 @@ var LuaVoice = class {
|
|
|
5901
6589
|
this.preemptiveGeneration = config.preemptiveGeneration;
|
|
5902
6590
|
this.interruption = config.interruption;
|
|
5903
6591
|
this.sttLanguage = config.sttLanguage;
|
|
6592
|
+
this.excludeTools = config.excludeTools;
|
|
5904
6593
|
this.tools = Object.freeze([
|
|
5905
6594
|
...config.tools ?? []
|
|
5906
6595
|
]);
|
|
@@ -5915,6 +6604,7 @@ function defineVoice(config) {
|
|
|
5915
6604
|
__name(defineVoice, "defineVoice");
|
|
5916
6605
|
|
|
5917
6606
|
// src/api-exports.ts
|
|
6607
|
+
init_dist();
|
|
5918
6608
|
init_baskets();
|
|
5919
6609
|
|
|
5920
6610
|
// src/interfaces/orders.ts
|
|
@@ -6398,6 +7088,44 @@ var Voice = {
|
|
|
6398
7088
|
const { getVoiceInstance: getVoiceInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
|
|
6399
7089
|
const voice = await getVoiceInstance2();
|
|
6400
7090
|
return voice.dispatchForSandbox(input);
|
|
7091
|
+
},
|
|
7092
|
+
async createSession(input) {
|
|
7093
|
+
const { getVoiceInstance: getVoiceInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
|
|
7094
|
+
const voice = await getVoiceInstance2();
|
|
7095
|
+
return voice.createSessionForSandbox(input ?? {});
|
|
7096
|
+
}
|
|
7097
|
+
};
|
|
7098
|
+
var Channels = {
|
|
7099
|
+
async send(input) {
|
|
7100
|
+
const { getChannelsSendInstance: getChannelsSendInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
|
|
7101
|
+
const channels = await getChannelsSendInstance2();
|
|
7102
|
+
return channels.sendForSandbox(input);
|
|
7103
|
+
},
|
|
7104
|
+
whatsapp: {
|
|
7105
|
+
async sendTemplate(input) {
|
|
7106
|
+
const { getChannelsSendInstance: getChannelsSendInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
|
|
7107
|
+
const channels = await getChannelsSendInstance2();
|
|
7108
|
+
return channels.sendWhatsAppTemplateForSandbox(input);
|
|
7109
|
+
},
|
|
7110
|
+
async sendReaction(input) {
|
|
7111
|
+
const { getChannelsSendInstance: getChannelsSendInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
|
|
7112
|
+
const channels = await getChannelsSendInstance2();
|
|
7113
|
+
return channels.sendWhatsAppReactionForSandbox(input);
|
|
7114
|
+
}
|
|
7115
|
+
},
|
|
7116
|
+
email: {
|
|
7117
|
+
async send(input) {
|
|
7118
|
+
const { getChannelsSendInstance: getChannelsSendInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
|
|
7119
|
+
const channels = await getChannelsSendInstance2();
|
|
7120
|
+
return channels.sendEmailForSandbox(input);
|
|
7121
|
+
}
|
|
7122
|
+
}
|
|
7123
|
+
};
|
|
7124
|
+
var Team = {
|
|
7125
|
+
async findMember(name) {
|
|
7126
|
+
const { getDirectoryInstance: getDirectoryInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
|
|
7127
|
+
const directory = await getDirectoryInstance2();
|
|
7128
|
+
return directory.resolveForSandbox(name);
|
|
6401
7129
|
}
|
|
6402
7130
|
};
|
|
6403
7131
|
var Templates = {
|
|
@@ -6531,6 +7259,10 @@ function defineDeviceTrigger(config) {
|
|
|
6531
7259
|
return new LuaDeviceTrigger(config);
|
|
6532
7260
|
}
|
|
6533
7261
|
__name(defineDeviceTrigger, "defineDeviceTrigger");
|
|
7262
|
+
function defineTrigger(config) {
|
|
7263
|
+
return new LuaTrigger(config);
|
|
7264
|
+
}
|
|
7265
|
+
__name(defineTrigger, "defineTrigger");
|
|
6534
7266
|
export {
|
|
6535
7267
|
AI,
|
|
6536
7268
|
Agents,
|
|
@@ -6538,6 +7270,8 @@ export {
|
|
|
6538
7270
|
BasketStatus,
|
|
6539
7271
|
Baskets,
|
|
6540
7272
|
CDN,
|
|
7273
|
+
CHANNEL_SEND_CHANNELS,
|
|
7274
|
+
Channels,
|
|
6541
7275
|
Data,
|
|
6542
7276
|
DataEntryInstance,
|
|
6543
7277
|
JobInstance,
|
|
@@ -6551,6 +7285,7 @@ export {
|
|
|
6551
7285
|
PostProcessor as LuaPostprocessor,
|
|
6552
7286
|
PreProcessor as LuaPreprocessor,
|
|
6553
7287
|
LuaSkill,
|
|
7288
|
+
LuaTrigger,
|
|
6554
7289
|
LuaVoice,
|
|
6555
7290
|
LuaVoiceTool,
|
|
6556
7291
|
LuaWebhook,
|
|
@@ -6561,6 +7296,7 @@ export {
|
|
|
6561
7296
|
PreProcessor,
|
|
6562
7297
|
ProductInstance,
|
|
6563
7298
|
Products,
|
|
7299
|
+
Team,
|
|
6564
7300
|
Templates,
|
|
6565
7301
|
ToolFlag,
|
|
6566
7302
|
User,
|
|
@@ -6568,6 +7304,7 @@ export {
|
|
|
6568
7304
|
Voice,
|
|
6569
7305
|
defineDevice,
|
|
6570
7306
|
defineDeviceTrigger,
|
|
7307
|
+
defineTrigger,
|
|
6571
7308
|
defineVoice,
|
|
6572
7309
|
env
|
|
6573
7310
|
};
|